@@ -160,8 +160,7 @@ strategy__. A transaction strategy is defined by the
160160---- 
161161	public interface PlatformTransactionManager { 
162162
163- 		TransactionStatus getTransaction( 
164- 				TransactionDefinition definition) throws TransactionException; 
163+ 		TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; 
165164
166165		void commit(TransactionStatus status) throws TransactionException; 
167166
@@ -2990,10 +2989,10 @@ An `update()` convenience method supports the retrieval of primary keys generate
29902989database. This support is part of the JDBC 3.0 standard; see Chapter 13.6 of the
29912990specification for details. The method takes a `PreparedStatementCreator` as its first
29922991argument, 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:
29972996
29982997[source,java,indent=0]
29992998[subs="verbatim,quotes"]
@@ -3244,27 +3243,26 @@ based on entries in a list. The entire list is used as the batch in this example
32443243[subs="verbatim,quotes"]
32453244---- 
32463245	public class JdbcActorDao implements ActorDao { 
3246+ 
32473247		private JdbcTemplate jdbcTemplate; 
32483248
32493249		public void setDataSource(DataSource dataSource) { 
32503250			this.jdbcTemplate = new JdbcTemplate(dataSource); 
32513251		} 
32523252
32533253		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 { 
32583258							ps.setString(1, actors.get(i).getFirstName()); 
32593259							ps.setString(2, actors.get(i).getLastName()); 
32603260							ps.setLong(3, actors.get(i).getId().longValue()); 
32613261						} 
3262- 
32633262						public int getBatchSize() { 
32643263							return actors.size(); 
32653264						} 
32663265					}); 
3267- 			return updateCounts; 
32683266		} 
32693267
32703268		// ... additional methods 
@@ -3287,27 +3285,27 @@ provide all parameter values in the call as a list. The framework loops over the
32873285values and uses an internal prepared statement setter. The API varies depending on
32883286whether you use named parameters. For the named parameters you provide an array of
32893287`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).
32923291
32933292This example shows a batch update using named parameters:
32943293
32953294[source,java,indent=0]
32963295[subs="verbatim,quotes"]
32973296---- 
32983297	public class JdbcActorDao implements ActorDao { 
3298+ 
32993299		private NamedParameterTemplate namedParameterJdbcTemplate; 
33003300
33013301		public void setDataSource(DataSource dataSource) { 
33023302			this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); 
33033303		} 
33043304
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( 
33083307					"update t_actor set first_name = :firstName, last_name = :lastName where id = :id", 
3309- 					batch); 
3310- 			return updateCounts; 
3308+ 					SqlParameterSourceUtils.createBatch(actors)); 
33113309		} 
33123310
33133311		// ... additional methods 
@@ -3336,15 +3334,12 @@ The same example using classic JDBC "?" placeholders:
33363334			List<Object[]> batch = new ArrayList<Object[]>(); 
33373335			for (Actor actor : actors) { 
33383336				Object[] values = new Object[] { 
3339- 						actor.getFirstName(), 
3340- 						actor.getLastName(), 
3341- 						actor.getId()}; 
3337+ 						actor.getFirstName(), actor.getLastName(), actor.getId()}; 
33423338				batch.add(values); 
33433339			} 
3344- 			int[] updateCounts =  jdbcTemplate.batchUpdate( 
3340+ 			return this. jdbcTemplate.batchUpdate( 
33453341					"update t_actor set first_name = ?, last_name = ? where id = ?", 
33463342					batch); 
3347- 			return updateCounts; 
33483343		} 
33493344
33503345		// ... additional methods 
@@ -3355,6 +3350,24 @@ All of the above batch update methods return an int array containing the number
33553350affected rows for each batch entry. This count is reported by the JDBC driver. If the
33563351count is not available, the JDBC driver returns a -2 value.
33573352
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+ 
33583371
33593372[[jdbc-batch-multi]]
33603373==== Batch operations with multiple batches
0 commit comments