diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java index 65f50b1b98..340683d76f 100644 --- a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java +++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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. @@ -33,6 +33,7 @@ import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.SingleColumnRowMapper; +import org.springframework.jdbc.core.SqlParameter; import org.springframework.jdbc.core.SqlRowSetResultSetExtractor; import org.springframework.jdbc.support.KeyHolder; import org.springframework.jdbc.support.rowset.SqlRowSet; @@ -276,8 +277,8 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations ParsedSql parsedSql = getParsedSql(sql); String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource); Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null); - int[] paramTypes = NamedParameterUtils.buildSqlTypeArray(parsedSql, paramSource); - PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, paramTypes); + List declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource); + PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters); if (keyColumnNames != null) { pscf.setGeneratedKeysColumnNames(keyColumnNames); } @@ -313,8 +314,8 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations ParsedSql parsedSql = getParsedSql(sql); String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource); Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null); - int[] paramTypes = NamedParameterUtils.buildSqlTypeArray(parsedSql, paramSource); - PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, paramTypes); + List declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource); + PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters); return pscf.newPreparedStatementCreator(params); } diff --git a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java index 7a34f412c6..799f007192 100644 --- a/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java +++ b/org.springframework.jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2011 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. @@ -19,6 +19,7 @@ package org.springframework.jdbc.core.namedparam; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -320,7 +321,7 @@ public abstract class NamedParameterUtils { } /** - * Convert a Map of parameter types to a corresponding int array. + * Convert parameter types from an SqlParameterSource into a corresponding int array. * This is necessary in order to reuse existing methods on JdbcTemplate. * Any named parameter types are placed in the correct position in the * Object array based on the parsed SQL statement info. @@ -329,14 +330,34 @@ public abstract class NamedParameterUtils { */ public static int[] buildSqlTypeArray(ParsedSql parsedSql, SqlParameterSource paramSource) { int[] sqlTypes = new int[parsedSql.getTotalParameterCount()]; - List paramNames = parsedSql.getParameterNames(); + List paramNames = parsedSql.getParameterNames(); for (int i = 0; i < paramNames.size(); i++) { - String paramName = (String) paramNames.get(i); + String paramName = paramNames.get(i); sqlTypes[i] = paramSource.getSqlType(paramName); } return sqlTypes; } + /** + * Convert parameter declarations from an SqlParameterSource to a corresponding List of SqlParameters. + * This is necessary in order to reuse existing methods on JdbcTemplate. + * The SqlParameter for a named parameter is placed in the correct position in the + * resulting list based on the parsed SQL statement info. + * @param parsedSql the parsed SQL statement + * @param paramSource the source for named parameters + */ + public static List buildSqlParameterList(ParsedSql parsedSql, SqlParameterSource paramSource) { + List paramNames = parsedSql.getParameterNames(); + List params = new LinkedList(); + for (String paramName : paramNames) { + SqlParameter param = new SqlParameter( + paramName, + paramSource.getSqlType(paramName), + paramSource.getTypeName(paramName)); + params.add(param); + } + return params; + } //------------------------------------------------------------------------- // Convenience methods operating on a plain SQL String diff --git a/org.springframework.jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterUtilsTests.java b/org.springframework.jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterUtilsTests.java index 16382eb954..2f498fb8c5 100644 --- a/org.springframework.jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterUtilsTests.java +++ b/org.springframework.jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2011 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. @@ -99,6 +99,22 @@ public class NamedParameterUtilsTests { .buildSqlTypeArray(NamedParameterUtils.parseSqlStatement("xxx :a :b :c xx :a :b"), namedParams)[4]); } + @Test + public void convertTypeMapToSqlParameterList() { + MapSqlParameterSource namedParams = new MapSqlParameterSource(); + namedParams.addValue("a", "a", 1).addValue("b", "b", 2).addValue("c", "c", 3, "SQL_TYPE"); + assertSame(3, NamedParameterUtils + .buildSqlParameterList(NamedParameterUtils.parseSqlStatement("xxx :a :b :c"), namedParams).size()); + assertSame(5, NamedParameterUtils + .buildSqlParameterList(NamedParameterUtils.parseSqlStatement("xxx :a :b :c xx :a :b"), namedParams).size()); + assertSame(5, NamedParameterUtils + .buildSqlParameterList(NamedParameterUtils.parseSqlStatement("xxx :a :a :a xx :a :a"), namedParams).size()); + assertEquals(2, NamedParameterUtils + .buildSqlParameterList(NamedParameterUtils.parseSqlStatement("xxx :a :b :c xx :a :b"), namedParams).get(4).getSqlType()); + assertEquals("SQL_TYPE", NamedParameterUtils + .buildSqlParameterList(NamedParameterUtils.parseSqlStatement("xxx :a :b :c"), namedParams).get(2).getTypeName()); + } + @Test(expected = InvalidDataAccessApiUsageException.class) public void buildValueArrayWithMissingParameterValue() throws Exception { String sql = "select count(0) from foo where id = :id";