From 3fa6723748e10cc3322735cce2da239d5e1a5a28 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sat, 9 Feb 2013 16:59:38 +0100 Subject: [PATCH] Added useful query variants without parameters to NamedParameterJdbcTemplate, for convenience in DAOs Also deprecated NamedParameterJdbcTemplate's queryForInt/Long operations in favor of queryForObject. Issue: SPR-10256 Issue: SPR-10257 --- .../namedparam/EmptySqlParameterSource.java | 49 +++++ .../NamedParameterJdbcOperations.java | 79 +++++++- .../NamedParameterJdbcTemplate.java | 22 ++- .../NamedParameterJdbcTemplateTests.java | 172 ++++++++++++++---- 4 files changed, 273 insertions(+), 49 deletions(-) create mode 100644 spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/EmptySqlParameterSource.java diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/EmptySqlParameterSource.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/EmptySqlParameterSource.java new file mode 100644 index 00000000000..a0b525f0dcd --- /dev/null +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/EmptySqlParameterSource.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.core.namedparam; + +/** + * A simple empty implementation of the {@link SqlParameterSource} interface. + * + * @author Juergen Hoeller + * @since 3.2.2 + */ +public class EmptySqlParameterSource implements SqlParameterSource { + + /** + * A shared instance of {@link EmptySqlParameterSource}. + */ + public static final EmptySqlParameterSource INSTANCE = new EmptySqlParameterSource(); + + + public boolean hasValue(String paramName) { + return false; + } + + public Object getValue(String paramName) throws IllegalArgumentException { + throw new IllegalArgumentException("This SqlParameterSource is empty"); + } + + public int getSqlType(String paramName) { + return TYPE_UNKNOWN; + } + + public String getTypeName(String paramName) { + return null; + } + +} diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java index a7f5c9f7c9c..91e20f3fcd9 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcOperations.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -88,6 +88,21 @@ public interface NamedParameterJdbcOperations { T execute(String sql, Map paramMap, PreparedStatementCallback action) throws DataAccessException; + /** + * Execute a JDBC data access operation, implemented as callback action + * working on a JDBC PreparedStatement. This allows for implementing arbitrary + * data access operations on a single Statement, within Spring's managed + * JDBC environment: that is, participating in Spring-managed transactions + * and converting JDBC SQLExceptions into Spring's DataAccessException hierarchy. + *

The callback action can return a result object, for example a + * domain object or a collection of domain objects. + * @param sql SQL to execute + * @param action callback object that specifies the action + * @return a result object returned by the action, or {@code null} + * @throws DataAccessException if there is any problem + */ + T execute(String sql, PreparedStatementCallback action) throws DataAccessException; + /** * Query given SQL to create a prepared statement from SQL and a list * of arguments to bind to the query, reading the ResultSet with a @@ -115,6 +130,19 @@ public interface NamedParameterJdbcOperations { T query(String sql, Map paramMap, ResultSetExtractor rse) throws DataAccessException; + /** + * Query given SQL to create a prepared statement from SQL, + * reading the ResultSet with a ResultSetExtractor. + *

Note: In contrast to the JdbcOperations method with the same signature, + * this query variant always uses a PreparedStatement. It is effectively + * equivalent to a query call with an empty parameter Map. + * @param sql SQL query to execute + * @param rse object that will extract results + * @return an arbitrary result object, as returned by the ResultSetExtractor + * @throws org.springframework.dao.DataAccessException if the query fails + */ + T query(String sql, ResultSetExtractor rse) throws DataAccessException; + /** * Query given SQL to create a prepared statement from SQL and a list of * arguments to bind to the query, reading the ResultSet on a per-row basis @@ -139,6 +167,18 @@ public interface NamedParameterJdbcOperations { */ void query(String sql, Map paramMap, RowCallbackHandler rch) throws DataAccessException; + /** + * Query given SQL to create a prepared statement from SQL, + * reading the ResultSet on a per-row basis with a RowCallbackHandler. + *

Note: In contrast to the JdbcOperations method with the same signature, + * this query variant always uses a PreparedStatement. It is effectively + * equivalent to a query call with an empty parameter Map. + * @param sql SQL query to execute + * @param rch object that will extract results, one row at a time + * @throws org.springframework.dao.DataAccessException if the query fails + */ + void query(String sql, RowCallbackHandler rch) throws DataAccessException; + /** * Query given SQL to create a prepared statement from SQL and a list * of arguments to bind to the query, mapping each row to a Java object @@ -166,6 +206,19 @@ public interface NamedParameterJdbcOperations { List query(String sql, Map paramMap, RowMapper rowMapper) throws DataAccessException; + /** + * Query given SQL to create a prepared statement from SQL, + * mapping each row to a Java object via a RowMapper. + *

Note: In contrast to the JdbcOperations method with the same signature, + * this query variant always uses a PreparedStatement. It is effectively + * equivalent to a query call with an empty parameter Map. + * @param sql SQL query to execute + * @param rowMapper object that will map one object per row + * @return the result List, containing mapped objects + * @throws org.springframework.dao.DataAccessException if the query fails + */ + List query(String sql, RowMapper rowMapper) throws DataAccessException; + /** * Query given SQL to create a prepared statement from SQL and a list * of arguments to bind to the query, mapping a single result row to a @@ -245,8 +298,7 @@ public interface NamedParameterJdbcOperations { * @param paramSource container of arguments to bind to the query * @return the result Map (one entry for each column, using the column name as the key) * @throws org.springframework.dao.IncorrectResultSizeDataAccessException - * if the query does not return exactly one row, or does not return exactly - * one column in that row + * if the query does not return exactly one row * @throws org.springframework.dao.DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForMap(String) * @see org.springframework.jdbc.core.ColumnMapRowMapper @@ -266,8 +318,7 @@ public interface NamedParameterJdbcOperations { * (leaving it to the PreparedStatement to guess the corresponding SQL type) * @return the result Map (one entry for each column, using the column name as the key) * @throws org.springframework.dao.IncorrectResultSizeDataAccessException - * if the query does not return exactly one row, or does not return exactly - * one column in that row + * if the query does not return exactly one row * @throws org.springframework.dao.DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForMap(String) * @see org.springframework.jdbc.core.ColumnMapRowMapper @@ -287,7 +338,9 @@ public interface NamedParameterJdbcOperations { * one column in that row * @throws org.springframework.dao.DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForLong(String) + * @deprecated in favor of {@link #queryForObject(String, SqlParameterSource, Class)} */ + @Deprecated long queryForLong(String sql, SqlParameterSource paramSource) throws DataAccessException; /** @@ -304,7 +357,9 @@ public interface NamedParameterJdbcOperations { * one column in that row * @throws org.springframework.dao.DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForLong(String) + * @deprecated in favor of {@link #queryForObject(String, Map, Class)} */ + @Deprecated long queryForLong(String sql, Map paramMap) throws DataAccessException; /** @@ -319,7 +374,9 @@ public interface NamedParameterJdbcOperations { * exactly one row, or does not return exactly one column in that row * @throws org.springframework.dao.DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForInt(String) + * @deprecated in favor of {@link #queryForObject(String, SqlParameterSource, Class)} */ + @Deprecated int queryForInt(String sql, SqlParameterSource paramSource) throws DataAccessException; /** @@ -335,7 +392,9 @@ public interface NamedParameterJdbcOperations { * exactly one row, or does not return exactly one column in that row * @throws org.springframework.dao.DataAccessException if the query fails * @see org.springframework.jdbc.core.JdbcTemplate#queryForInt(String) + * @deprecated in favor of {@link #queryForObject(String, Map, Class)} */ + @Deprecated int queryForInt(String sql, Map paramMap) throws DataAccessException; /** @@ -378,8 +437,8 @@ public interface NamedParameterJdbcOperations { * list of arguments to bind to the query, expecting a result list. *

The results will be mapped to a List (one entry for each row) of * Maps (one entry for each column, using the column name as the key). - * Thus Each element in the list will be of the form returned by this interface's - * queryForMap() methods. + * Each element in the list will be of the form returned by this interface's + * {@code queryForMap} methods. * @param sql SQL query to execute * @param paramSource container of arguments to bind to the query * @return a List that contains a Map per row @@ -394,7 +453,7 @@ public interface NamedParameterJdbcOperations { *

The results will be mapped to a List (one entry for each row) of * Maps (one entry for each column, using the column name as the key). * Each element in the list will be of the form returned by this interface's - * queryForMap() methods. + * {@code queryForMap} methods. * @param sql SQL query to execute * @param paramMap map of parameters to bind to the query * (leaving it to the PreparedStatement to guess the corresponding SQL type) @@ -499,7 +558,7 @@ public interface NamedParameterJdbcOperations { * @param batchValues the array of Maps containing the batch of arguments for the query * @return an array containing the numbers of rows affected by each update in the batch */ - public int[] batchUpdate(String sql, Map[] batchValues); + int[] batchUpdate(String sql, Map[] batchValues); /** * Execute a batch using the supplied SQL statement with the batch of supplied arguments. @@ -507,6 +566,6 @@ public interface NamedParameterJdbcOperations { * @param batchArgs the array of {@link SqlParameterSource} containing the batch of arguments for the query * @return an array containing the numbers of rows affected by each update in the batch */ - public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs); + int[] batchUpdate(String sql, SqlParameterSource[] batchArgs); } diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java index 1abfdea3c21..d8258cefc95 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -137,6 +137,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations return execute(sql, new MapSqlParameterSource(paramMap), action); } + public T execute(String sql, PreparedStatementCallback action) throws DataAccessException { + return execute(sql, EmptySqlParameterSource.INSTANCE, action); + } + public T query(String sql, SqlParameterSource paramSource, ResultSetExtractor rse) throws DataAccessException { @@ -149,6 +153,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations return query(sql, new MapSqlParameterSource(paramMap), rse); } + public T query(String sql, ResultSetExtractor rse) throws DataAccessException { + return query(sql, EmptySqlParameterSource.INSTANCE, rse); + } + public void query(String sql, SqlParameterSource paramSource, RowCallbackHandler rch) throws DataAccessException { @@ -161,6 +169,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations query(sql, new MapSqlParameterSource(paramMap), rch); } + public void query(String sql, RowCallbackHandler rch) throws DataAccessException { + query(sql, EmptySqlParameterSource.INSTANCE, rch); + } + public List query(String sql, SqlParameterSource paramSource, RowMapper rowMapper) throws DataAccessException { @@ -173,6 +185,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations return query(sql, new MapSqlParameterSource(paramMap), rowMapper); } + public List query(String sql, RowMapper rowMapper) throws DataAccessException { + return query(sql, EmptySqlParameterSource.INSTANCE, rowMapper); + } + public T queryForObject(String sql, SqlParameterSource paramSource, RowMapper rowMapper) throws DataAccessException { @@ -206,20 +222,24 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations return queryForObject(sql, paramMap, new ColumnMapRowMapper()); } + @Deprecated public long queryForLong(String sql, SqlParameterSource paramSource) throws DataAccessException { Number number = queryForObject(sql, paramSource, Long.class); return (number != null ? number.longValue() : 0); } + @Deprecated public long queryForLong(String sql, Map paramMap) throws DataAccessException { return queryForLong(sql, new MapSqlParameterSource(paramMap)); } + @Deprecated public int queryForInt(String sql, SqlParameterSource paramSource) throws DataAccessException { Number number = queryForObject(sql, paramSource, Integer.class); return (number != null ? number.intValue() : 0); } + @Deprecated public int queryForInt(String sql, Map paramMap) throws DataAccessException { return queryForInt(sql, new MapSqlParameterSource(paramMap)); } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java index 6564fe5ee7a..c17c8bbc02d 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +16,6 @@ package org.springframework.jdbc.core.namedparam; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.BDDMockito.given; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; @@ -36,13 +27,13 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; - import javax.sql.DataSource; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; + import org.springframework.dao.DataAccessException; import org.springframework.jdbc.Customer; import org.springframework.jdbc.core.JdbcOperations; @@ -53,6 +44,14 @@ import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.SqlParameterValue; +import static org.junit.Assert.*; +import static org.mockito.BDDMockito.*; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + /** * @author Rick Evans * @author Juergen Hoeller @@ -64,6 +63,8 @@ public class NamedParameterJdbcTemplateTests { "select id, forename from custmr where id = :id and country = :country"; private static final String SELECT_NAMED_PARAMETERS_PARSED = "select id, forename from custmr where id = ? and country = ?"; + private static final String SELECT_NO_PARAMETERS = + "select id, forename from custmr"; private static final String UPDATE_NAMED_PARAMETERS = "update seat_status set booking_id = null where performance_id = :perfId and price_band_id = :priceId"; @@ -161,33 +162,23 @@ public class NamedParameterJdbcTemplateTests { verify(connection).close(); } - @Test public void testUpdate() throws SQLException { - given(preparedStatement.executeUpdate()).willReturn(1); - - params.put("perfId", 1); - params.put("priceId", 1); - int rowsAffected = namedParameterTemplate.update(UPDATE_NAMED_PARAMETERS, params); - - assertEquals(1, rowsAffected); - verify(connection).prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED); - verify(preparedStatement).setObject(1, 1); - verify(preparedStatement).setObject(2, 1); - verify(preparedStatement).close(); - verify(connection).close(); - } - @Test - public void testUpdateWithTypedParameters() throws SQLException { + public void testExecuteNoParameters() throws SQLException { given(preparedStatement.executeUpdate()).willReturn(1); - params.put("perfId", new SqlParameterValue(Types.DECIMAL, 1)); - params.put("priceId", new SqlParameterValue(Types.INTEGER, 1)); - int rowsAffected = namedParameterTemplate.update(UPDATE_NAMED_PARAMETERS, params); + Object result = namedParameterTemplate.execute(SELECT_NO_PARAMETERS, + new PreparedStatementCallback() { + @Override + public Object doInPreparedStatement(PreparedStatement ps) + throws SQLException { + assertEquals(preparedStatement, ps); + ps.executeQuery(); + return "result"; + } + }); - assertEquals(1, rowsAffected); - verify(connection).prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED); - verify(preparedStatement).setObject(1, 1, Types.DECIMAL); - verify(preparedStatement).setObject(2, 1, Types.INTEGER); + assertEquals("result", result); + verify(connection).prepareStatement(SELECT_NO_PARAMETERS); verify(preparedStatement).close(); verify(connection).close(); } @@ -222,6 +213,32 @@ public class NamedParameterJdbcTemplateTests { verify(connection).close(); } + @Test + public void testQueryWithResultSetExtractorNoParameters() throws SQLException { + given(resultSet.next()).willReturn(true); + given(resultSet.getInt("id")).willReturn(1); + given(resultSet.getString("forename")).willReturn("rod"); + + Customer cust = namedParameterTemplate.query(SELECT_NO_PARAMETERS, + new ResultSetExtractor() { + @Override + public Customer extractData(ResultSet rs) throws SQLException, + DataAccessException { + rs.next(); + Customer cust = new Customer(); + cust.setId(rs.getInt(COLUMN_NAMES[0])); + cust.setForename(rs.getString(COLUMN_NAMES[1])); + return cust; + } + }); + + assertTrue("Customer id was assigned correctly", cust.getId() == 1); + assertTrue("Customer forename was assigned correctly", cust.getForename().equals("rod")); + verify(connection).prepareStatement(SELECT_NO_PARAMETERS); + verify(preparedStatement).close(); + verify(connection).close(); + } + @Test public void testQueryWithRowCallbackHandler() throws SQLException { given(resultSet.next()).willReturn(true, false); @@ -251,6 +268,31 @@ public class NamedParameterJdbcTemplateTests { verify(connection).close(); } + @Test + public void testQueryWithRowCallbackHandlerNoParameters() throws SQLException { + given(resultSet.next()).willReturn(true, false); + given(resultSet.getInt("id")).willReturn(1); + given(resultSet.getString("forename")).willReturn("rod"); + + final List customers = new LinkedList(); + namedParameterTemplate.query(SELECT_NO_PARAMETERS, new RowCallbackHandler() { + @Override + public void processRow(ResultSet rs) throws SQLException { + Customer cust = new Customer(); + cust.setId(rs.getInt(COLUMN_NAMES[0])); + cust.setForename(rs.getString(COLUMN_NAMES[1])); + customers.add(cust); + } + }); + + assertEquals(1, customers.size()); + assertTrue("Customer id was assigned correctly", customers.get(0).getId() == 1); + assertTrue("Customer forename was assigned correctly", customers.get(0).getForename().equals("rod")); + verify(connection).prepareStatement(SELECT_NO_PARAMETERS); + verify(preparedStatement).close(); + verify(connection).close(); + } + @Test public void testQueryWithRowMapper() throws SQLException { given(resultSet.next()).willReturn(true, false); @@ -279,6 +321,30 @@ public class NamedParameterJdbcTemplateTests { verify(connection).close(); } + @Test + public void testQueryWithRowMapperNoParameters() throws SQLException { + given(resultSet.next()).willReturn(true, false); + given(resultSet.getInt("id")).willReturn(1); + given(resultSet.getString("forename")).willReturn("rod"); + + List customers = namedParameterTemplate.query(SELECT_NO_PARAMETERS, + new RowMapper() { + @Override + public Customer mapRow(ResultSet rs, int rownum) throws SQLException { + Customer cust = new Customer(); + cust.setId(rs.getInt(COLUMN_NAMES[0])); + cust.setForename(rs.getString(COLUMN_NAMES[1])); + return cust; + } + }); + assertEquals(1, customers.size()); + assertTrue("Customer id was assigned correctly", customers.get(0).getId() == 1); + assertTrue("Customer forename was assigned correctly", customers.get(0).getForename().equals("rod")); + verify(connection).prepareStatement(SELECT_NO_PARAMETERS); + verify(preparedStatement).close(); + verify(connection).close(); + } + @Test public void testQueryForObjectWithRowMapper() throws SQLException { given(resultSet.next()).willReturn(true, false); @@ -307,8 +373,39 @@ public class NamedParameterJdbcTemplateTests { } @Test - public void testBatchUpdateWithPlainMap() throws Exception { + public void testUpdate() throws SQLException { + given(preparedStatement.executeUpdate()).willReturn(1); + + params.put("perfId", 1); + params.put("priceId", 1); + int rowsAffected = namedParameterTemplate.update(UPDATE_NAMED_PARAMETERS, params); + + assertEquals(1, rowsAffected); + verify(connection).prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED); + verify(preparedStatement).setObject(1, 1); + verify(preparedStatement).setObject(2, 1); + verify(preparedStatement).close(); + verify(connection).close(); + } + + @Test + public void testUpdateWithTypedParameters() throws SQLException { + given(preparedStatement.executeUpdate()).willReturn(1); + + params.put("perfId", new SqlParameterValue(Types.DECIMAL, 1)); + params.put("priceId", new SqlParameterValue(Types.INTEGER, 1)); + int rowsAffected = namedParameterTemplate.update(UPDATE_NAMED_PARAMETERS, params); + + assertEquals(1, rowsAffected); + verify(connection).prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED); + verify(preparedStatement).setObject(1, 1, Types.DECIMAL); + verify(preparedStatement).setObject(2, 1, Types.INTEGER); + verify(preparedStatement).close(); + verify(connection).close(); + } + @Test + public void testBatchUpdateWithPlainMap() throws Exception { @SuppressWarnings("unchecked") final Map[] ids = new Map[2]; ids[0] = Collections.singletonMap("id", 100); @@ -335,7 +432,7 @@ public class NamedParameterJdbcTemplateTests { @Test public void testBatchUpdateWithSqlParameterSource() throws Exception { - final SqlParameterSource[] ids = new SqlParameterSource[2]; + SqlParameterSource[] ids = new SqlParameterSource[2]; ids[0] = new MapSqlParameterSource("id", 100); ids[1] = new MapSqlParameterSource("id", 200); final int[] rowsAffected = new int[] { 1, 2 }; @@ -360,8 +457,7 @@ public class NamedParameterJdbcTemplateTests { @Test public void testBatchUpdateWithSqlParameterSourcePlusTypeInfo() throws Exception { - - final SqlParameterSource[] ids = new SqlParameterSource[2]; + SqlParameterSource[] ids = new SqlParameterSource[2]; ids[0] = new MapSqlParameterSource().addValue("id", 100, Types.NUMERIC); ids[1] = new MapSqlParameterSource().addValue("id", 200, Types.NUMERIC); final int[] rowsAffected = new int[] { 1, 2 };