From d5f34ed64112eefc13065f45ce107c727207db51 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 14 Nov 2017 12:30:13 +0100 Subject: [PATCH] Correctly handle NVARCHAR, LONGNVARCHAR and NCLOBs Issue: SPR-16154 --- .../jdbc/core/StatementCreatorUtils.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java b/spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java index a1092a5f6a4..14c2c94e7eb 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/core/StatementCreatorUtils.java @@ -68,13 +68,16 @@ public abstract class StatementCreatorUtils { * System property that instructs Spring to ignore {@link java.sql.ParameterMetaData#getParameterType} * completely, i.e. to never even attempt to retrieve {@link PreparedStatement#getParameterMetaData()} * for {@link StatementCreatorUtils#setNull} calls. - *

The default is "false", trying {@code getParameterType} calls first and falling back to + *

The effective default is "false", trying {@code getParameterType} calls first and falling back to * {@link PreparedStatement#setNull} / {@link PreparedStatement#setObject} calls based on well-known * behavior of common databases. Spring records JDBC drivers with non-working {@code getParameterType} * implementations and won't attempt to call that method for that driver again, always falling back. *

Consider switching this flag to "true" if you experience misbehavior at runtime, e.g. with * a connection pool setting back the {@link PreparedStatement} instance in case of an exception * thrown from {@code getParameterType} (as reported on JBoss AS 7). + *

Note that this flag is "true" by default on Oracle 12c since there can be leaks created by + * {@code getParameterType} calls in such a scenario. You need to explicitly set the flag to + * "false" in order to enforce the use of {@code getParameterType} against Oracle drivers. */ public static final String IGNORE_GETPARAMETERTYPE_PROPERTY_NAME = "spring.jdbc.getParameterType.ignore"; @@ -339,10 +342,12 @@ public abstract class StatementCreatorUtils { else if (inValue instanceof SqlValue) { ((SqlValue) inValue).setValue(ps, paramIndex); } - else if (sqlType == Types.VARCHAR || sqlType == Types.NVARCHAR || - sqlType == Types.LONGVARCHAR || sqlType == Types.LONGNVARCHAR) { + else if (sqlType == Types.VARCHAR || sqlType == Types.LONGVARCHAR ) { ps.setString(paramIndex, inValue.toString()); } + else if (sqlType == Types.NVARCHAR || sqlType == Types.LONGNVARCHAR) { + ps.setNString(paramIndex, inValue.toString()); + } else if ((sqlType == Types.CLOB || sqlType == Types.NCLOB) && isStringValue(inValue.getClass())) { String strVal = inValue.toString(); if (strVal.length() > 4000) { @@ -364,8 +369,13 @@ public abstract class StatementCreatorUtils { logger.debug("JDBC driver does not support JDBC 4.0 'setClob(int, Reader, long)' method", ex); } } - // Fallback: regular setString binding - ps.setString(paramIndex, strVal); + // Fallback: setString or setNString binding + if (sqlType == Types.NCLOB) { + ps.setNString(paramIndex, strVal); + } + else { + ps.setString(paramIndex, strVal); + } } else if (sqlType == Types.DECIMAL || sqlType == Types.NUMERIC) { if (inValue instanceof BigDecimal) {