Skip to content

Commit f0a1ff2

Browse files
committed
JDBC parameter binding uses JDBC 3.0 ParameterMetaData (if available) for type determination
Forward-ported from 3.1.2, with minor modifications for defensiveness against the JDBC driver. Issue: SPR-10084
1 parent 68970b7 commit f0a1ff2

File tree

2 files changed

+34
-20
lines changed

2 files changed

+34
-20
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/core/PreparedStatementCreatorFactory.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -146,7 +146,7 @@ public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
146146
* Return a new PreparedStatementSetter for the given parameters.
147147
* @param params list of parameters (may be {@code null})
148148
*/
149-
public PreparedStatementSetter newPreparedStatementSetter(List params) {
149+
public PreparedStatementSetter newPreparedStatementSetter(List<?> params) {
150150
return new PreparedStatementCreatorImpl(params != null ? params : Collections.emptyList());
151151
}
152152

@@ -225,7 +225,7 @@ public PreparedStatementCreatorImpl(String actualSql, List parameters) {
225225
}
226226

227227
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
228-
PreparedStatement ps = null;
228+
PreparedStatement ps;
229229
if (generatedKeysColumnNames != null || returnGeneratedKeys) {
230230
try {
231231
if (generatedKeysColumnNames != null) {
@@ -235,10 +235,10 @@ public PreparedStatement createPreparedStatement(Connection con) throws SQLExcep
235235
ps = con.prepareStatement(this.actualSql, PreparedStatement.RETURN_GENERATED_KEYS);
236236
}
237237
}
238-
catch (AbstractMethodError ex) {
238+
catch (AbstractMethodError err) {
239239
throw new InvalidDataAccessResourceUsageException(
240-
"The JDBC driver is not compliant to JDBC 3.0 and thus " +
241-
"does not support retrieval of auto-generated keys", ex);
240+
"Your JDBC driver is not compliant with JDBC 3.0 - " +
241+
"it does not support retrieval of auto-generated keys", err);
242242
}
243243
}
244244
else if (resultSetType == ResultSet.TYPE_FORWARD_ONLY && !updatableResults) {
@@ -263,7 +263,7 @@ public void setValues(PreparedStatement ps) throws SQLException {
263263
int sqlColIndx = 1;
264264
for (int i = 0; i < this.parameters.size(); i++) {
265265
Object in = this.parameters.get(i);
266-
SqlParameter declaredParameter = null;
266+
SqlParameter declaredParameter;
267267
// SqlParameterValue overrides declared parameter metadata, in particular for
268268
// independence from the declared parameter position in case of named parameters.
269269
if (in instanceof SqlParameterValue) {

spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java

+27-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222
import java.sql.Blob;
2323
import java.sql.Clob;
2424
import java.sql.DatabaseMetaData;
25+
import java.sql.ParameterMetaData;
2526
import java.sql.PreparedStatement;
2627
import java.sql.SQLException;
2728
import java.sql.Types;
@@ -189,7 +190,7 @@ private static void setParameterValueInternal(
189190
if (inValue instanceof SqlParameterValue) {
190191
SqlParameterValue parameterValue = (SqlParameterValue) inValue;
191192
if (logger.isDebugEnabled()) {
192-
logger.debug("Overriding typeinfo with runtime info from SqlParameterValue: column index " + paramIndex +
193+
logger.debug("Overriding type info with runtime info from SqlParameterValue: column index " + paramIndex +
193194
", SQL type " + parameterValue.getSqlType() +
194195
", Type name " + parameterValue.getTypeName());
195196
}
@@ -228,18 +229,31 @@ private static void setNull(PreparedStatement ps, int paramIndex, int sqlType, S
228229
boolean useSetObject = false;
229230
sqlType = Types.NULL;
230231
try {
231-
DatabaseMetaData dbmd = ps.getConnection().getMetaData();
232-
String databaseProductName = dbmd.getDatabaseProductName();
233-
String jdbcDriverName = dbmd.getDriverName();
234-
if (databaseProductName.startsWith("Informix") ||
235-
jdbcDriverName.startsWith("Microsoft SQL Server")) {
236-
useSetObject = true;
232+
ParameterMetaData pmd = null;
233+
try {
234+
pmd = ps.getParameterMetaData();
237235
}
238-
else if (databaseProductName.startsWith("DB2") ||
239-
jdbcDriverName.startsWith("jConnect") ||
240-
jdbcDriverName.startsWith("SQLServer")||
241-
jdbcDriverName.startsWith("Apache Derby")) {
242-
sqlType = Types.VARCHAR;
236+
catch (Throwable ex) {
237+
// JDBC driver not compliant with JDBC 3.0
238+
// -> proceed with database-specific checks
239+
}
240+
if (pmd != null) {
241+
sqlType = pmd.getParameterType(paramIndex);
242+
}
243+
else {
244+
DatabaseMetaData dbmd = ps.getConnection().getMetaData();
245+
String databaseProductName = dbmd.getDatabaseProductName();
246+
String jdbcDriverName = dbmd.getDriverName();
247+
if (databaseProductName.startsWith("Informix") ||
248+
jdbcDriverName.startsWith("Microsoft SQL Server")) {
249+
useSetObject = true;
250+
}
251+
else if (databaseProductName.startsWith("DB2") ||
252+
jdbcDriverName.startsWith("jConnect") ||
253+
jdbcDriverName.startsWith("SQLServer")||
254+
jdbcDriverName.startsWith("Apache Derby")) {
255+
sqlType = Types.VARCHAR;
256+
}
243257
}
244258
}
245259
catch (Throwable ex) {

0 commit comments

Comments
 (0)