@@ -160,8 +160,7 @@ strategy__. A transaction strategy is defined by the
160
160
----
161
161
public interface PlatformTransactionManager {
162
162
163
- TransactionStatus getTransaction(
164
- TransactionDefinition definition) throws TransactionException;
163
+ TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
165
164
166
165
void commit(TransactionStatus status) throws TransactionException;
167
166
@@ -2990,10 +2989,10 @@ An `update()` convenience method supports the retrieval of primary keys generate
2990
2989
database. This support is part of the JDBC 3.0 standard; see Chapter 13.6 of the
2991
2990
specification for details. The method takes a `PreparedStatementCreator` as its first
2992
2991
argument, and this is the way the required insert statement is specified. The other
2993
- argument is a `KeyHolder`, which contains the generated key on successful return from
2994
- the update. There is not a standard single way to create an appropriate
2995
- `PreparedStatement` (which explains why the method signature is the way it is). The
2996
- following example works on Oracle but may not work on other platforms:
2992
+ argument is a `KeyHolder`, which contains the generated key on successful return from the
2993
+ update. There is not a standard single way to create an appropriate `PreparedStatement`
2994
+ (which explains why the method signature is the way it is). The following example works
2995
+ on Oracle but may not work on other platforms:
2997
2996
2998
2997
[source,java,indent=0]
2999
2998
[subs="verbatim,quotes"]
@@ -3244,27 +3243,26 @@ based on entries in a list. The entire list is used as the batch in this example
3244
3243
[subs="verbatim,quotes"]
3245
3244
----
3246
3245
public class JdbcActorDao implements ActorDao {
3246
+
3247
3247
private JdbcTemplate jdbcTemplate;
3248
3248
3249
3249
public void setDataSource(DataSource dataSource) {
3250
3250
this.jdbcTemplate = new JdbcTemplate(dataSource);
3251
3251
}
3252
3252
3253
3253
public int[] batchUpdate(final List<Actor> actors) {
3254
- int[] updateCounts = jdbcTemplate.batchUpdate("update t_actor set first_name = ?, " +
3255
- "last_name = ? where id = ?",
3256
- new BatchPreparedStatementSetter() {
3257
- public void setValues(PreparedStatement ps, int i) throws SQLException {
3254
+ return this. jdbcTemplate.batchUpdate(
3255
+ "update t_actor set first_name = ?, last_name = ? where id = ?",
3256
+ new BatchPreparedStatementSetter() {
3257
+ public void setValues(PreparedStatement ps, int i) throws SQLException {
3258
3258
ps.setString(1, actors.get(i).getFirstName());
3259
3259
ps.setString(2, actors.get(i).getLastName());
3260
3260
ps.setLong(3, actors.get(i).getId().longValue());
3261
3261
}
3262
-
3263
3262
public int getBatchSize() {
3264
3263
return actors.size();
3265
3264
}
3266
3265
});
3267
- return updateCounts;
3268
3266
}
3269
3267
3270
3268
// ... additional methods
@@ -3287,27 +3285,27 @@ provide all parameter values in the call as a list. The framework loops over the
3287
3285
values and uses an internal prepared statement setter. The API varies depending on
3288
3286
whether you use named parameters. For the named parameters you provide an array of
3289
3287
`SqlParameterSource`, one entry for each member of the batch. You can use the
3290
- `SqlParameterSource.createBatch` method to create this array, passing in either an array
3291
- of JavaBeans or an array of Maps containing the parameter values.
3288
+ `SqlParameterSourceUtils.createBatch` convenience methods to create this array, passing
3289
+ in an array of bean-style objects (with getter methods corresponding to parameters)
3290
+ and/or String-keyed Maps (containing the corresponding parameters as values).
3292
3291
3293
3292
This example shows a batch update using named parameters:
3294
3293
3295
3294
[source,java,indent=0]
3296
3295
[subs="verbatim,quotes"]
3297
3296
----
3298
3297
public class JdbcActorDao implements ActorDao {
3298
+
3299
3299
private NamedParameterTemplate namedParameterJdbcTemplate;
3300
3300
3301
3301
public void setDataSource(DataSource dataSource) {
3302
3302
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
3303
3303
}
3304
3304
3305
- public int[] batchUpdate(final List<Actor> actors) {
3306
- SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(actors.toArray());
3307
- int[] updateCounts = namedParameterJdbcTemplate.batchUpdate(
3305
+ public int[] batchUpdate(List<Actor> actors) {
3306
+ return this.namedParameterJdbcTemplate.batchUpdate(
3308
3307
"update t_actor set first_name = :firstName, last_name = :lastName where id = :id",
3309
- batch);
3310
- return updateCounts;
3308
+ SqlParameterSourceUtils.createBatch(actors));
3311
3309
}
3312
3310
3313
3311
// ... additional methods
@@ -3336,15 +3334,12 @@ The same example using classic JDBC "?" placeholders:
3336
3334
List<Object[]> batch = new ArrayList<Object[]>();
3337
3335
for (Actor actor : actors) {
3338
3336
Object[] values = new Object[] {
3339
- actor.getFirstName(),
3340
- actor.getLastName(),
3341
- actor.getId()};
3337
+ actor.getFirstName(), actor.getLastName(), actor.getId()};
3342
3338
batch.add(values);
3343
3339
}
3344
- int[] updateCounts = jdbcTemplate.batchUpdate(
3340
+ return this. jdbcTemplate.batchUpdate(
3345
3341
"update t_actor set first_name = ?, last_name = ? where id = ?",
3346
3342
batch);
3347
- return updateCounts;
3348
3343
}
3349
3344
3350
3345
// ... additional methods
@@ -3355,6 +3350,24 @@ All of the above batch update methods return an int array containing the number
3355
3350
affected rows for each batch entry. This count is reported by the JDBC driver. If the
3356
3351
count is not available, the JDBC driver returns a -2 value.
3357
3352
3353
+ [NOTE]
3354
+ ====
3355
+ In such a scenario with automatic setting of values on an underlying `PreparedStatement`,
3356
+ the corresponding JDBC type for each value needs to be derived from the given Java type.
3357
+ While this usually works well, there is a potential for issues, e.g. with Map-contained
3358
+ `null` values: Spring will by default call `ParameterMetaData.getParameterType` in such a
3359
+ case which may be expensive with your JDBC driver. Please make sure to use a recent driver
3360
+ version, and consider setting the "spring.jdbc.getParameterType.ignore" property to "true"
3361
+ (as a JVM system property or in a `spring.properties` file in the root of your classpath)
3362
+ if you encounter a performance issue, e.g. as reported on Oracle 12c (SPR-16139).
3363
+
3364
+ Alternatively, simply consider specifying the corresponding JDBC types explicitly:
3365
+ either via a 'BatchPreparedStatementSetter' as shown above, or via an explicit type
3366
+ array given to a 'List<Object[]>' based call, or via 'registerSqlType' calls on a
3367
+ custom 'MapSqlParameterSource' instance, or via a 'BeanPropertySqlParameterSource'
3368
+ which derives the SQL type from the Java-declared property type even for a null value.
3369
+ ====
3370
+
3358
3371
3359
3372
[[jdbc-batch-multi]]
3360
3373
==== Batch operations with multiple batches
0 commit comments