From 390880448671077311aaa34f75182c4bf55b57c2 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sat, 27 Sep 2014 00:40:35 +0200 Subject: [PATCH] StatementCreatorUtils uses setClob/setNClob with stream argument in case of typed String value exceeding 4000 characters (for Oracle compatibility) Issue: SPR-12240 --- .../jdbc/core/StatementCreatorUtils.java | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 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 a28072ffb1..f760192c99 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 @@ -16,6 +16,7 @@ package org.springframework.jdbc.core; +import java.io.StringReader; import java.io.StringWriter; import java.math.BigDecimal; import java.math.BigInteger; @@ -24,6 +25,7 @@ import java.sql.Clob; import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; import java.sql.Types; import java.util.Arrays; import java.util.Calendar; @@ -319,10 +321,33 @@ public abstract class StatementCreatorUtils { ((SqlValue) inValue).setValue(ps, paramIndex); } else if (sqlType == Types.VARCHAR || sqlType == Types.NVARCHAR || - sqlType == Types.LONGVARCHAR || sqlType == Types.LONGNVARCHAR || - ((sqlType == Types.CLOB || sqlType == Types.NCLOB) && isStringValue(inValue.getClass()))) { + sqlType == Types.LONGVARCHAR || sqlType == Types.LONGNVARCHAR) { ps.setString(paramIndex, inValue.toString()); } + else if ((sqlType == Types.CLOB || sqlType == Types.NCLOB) && isStringValue(inValue.getClass())) { + String strVal = inValue.toString(); + if (strVal.length() > 4000) { + // Necessary for older Oracle drivers, in particular when running against an Oracle 10 database. + // Should also work fine against other drivers/databases since it uses standard JDBC 4.0 API. + try { + if (sqlType == Types.NCLOB) { + ps.setNClob(paramIndex, new StringReader(strVal), strVal.length()); + } + else { + ps.setClob(paramIndex, new StringReader(strVal), strVal.length()); + } + return; + } + catch (AbstractMethodError err) { + logger.debug("JDBC driver does not implement JDBC 4.0 'setClob(int, Reader, long)' method", err); + } + catch (SQLFeatureNotSupportedException ex) { + logger.debug("JDBC driver does not support JDBC 4.0 'setClob(int, Reader, long)' method", ex); + } + } + // Fallback: regular setString binding + ps.setString(paramIndex, strVal); + } else if (sqlType == Types.DECIMAL || sqlType == Types.NUMERIC) { if (inValue instanceof BigDecimal) { ps.setBigDecimal(paramIndex, (BigDecimal) inValue);