Backport further refinements from the nullability efforts

Issue: SPR-15656
This commit is contained in:
Juergen Hoeller
2017-09-27 15:20:17 +02:00
parent 5f167fd7f8
commit cc70fdcbeb
50 changed files with 382 additions and 532 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2017 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.
@@ -25,20 +25,21 @@ import java.util.List;
* within the framework.
*
* @author Thomas Risberg
* @since 3.0
*/
public abstract class BatchUpdateUtils {
public static int[] executeBatchUpdate(String sql, final List<Object[]> batchValues, final int[] columnTypes, JdbcOperations jdbcOperations) {
public static int[] executeBatchUpdate(
String sql, final List<Object[]> batchValues, final int[] columnTypes, JdbcOperations jdbcOperations) {
return jdbcOperations.batchUpdate(
sql,
new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
Object[] values = batchValues.get(i);
setStatementParameters(values, ps, columnTypes);
}
@Override
public int getBatchSize() {
return batchValues.size();
@@ -46,7 +47,9 @@ public abstract class BatchUpdateUtils {
});
}
protected static void setStatementParameters(Object[] values, PreparedStatement ps, int[] columnTypes) throws SQLException {
protected static void setStatementParameters(Object[] values, PreparedStatement ps, int[] columnTypes)
throws SQLException {
int colIndex = 0;
for (Object value : values) {
colIndex++;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@@ -1267,11 +1267,14 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
* @param param the corresponding stored procedure parameter
* @return Map that contains returned results
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
protected Map<String, Object> processResultSet(ResultSet rs, ResultSetSupportingSqlParameter param) throws SQLException {
@SuppressWarnings({"unchecked", "rawtypes"})
protected Map<String, Object> processResultSet(ResultSet rs, ResultSetSupportingSqlParameter param)
throws SQLException {
if (rs == null) {
return Collections.emptyMap();
}
Map<String, Object> returnedResults = new HashMap<String, Object>();
try {
ResultSet rsToUse = rs;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@@ -119,7 +119,7 @@ public abstract class StatementCreatorUtils {
/**
* Derive a default SQL type from the given Java type.
* @param javaType the Java type to translate
* @return the corresponding SQL type, or {@code null} if none found
* @return the corresponding SQL type, or {@link SqlTypeValue#TYPE_UNKNOWN} if none found
*/
public static int javaTypeToSqlParameterType(Class<?> javaType) {
Integer sqlType = javaTypeToSqlTypeMap.get(javaType);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2017 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.
@@ -234,6 +234,14 @@ public class CallMetaDataContext {
}
/**
* Initialize this class with metadata from the database.
* @param dataSource the DataSource used to retrieve metadata
*/
public void initializeMetaData(DataSource dataSource) {
this.metaDataProvider = CallMetaDataProviderFactory.createMetaDataProvider(dataSource, this);
}
/**
* Create a ReturnResultSetParameter/SqlOutParameter depending on the support provided
* by the JDBC driver used for the database in use.
@@ -278,14 +286,6 @@ public class CallMetaDataContext {
return this.callParameters;
}
/**
* Initialize this class with metadata from the database.
* @param dataSource the DataSource used to retrieve metadata
*/
public void initializeMetaData(DataSource dataSource) {
this.metaDataProvider = CallMetaDataProviderFactory.createMetaDataProvider(dataSource, this);
}
/**
* Process the list of parameters provided, and if procedure column metadata is used,
* the parameters will be matched against the metadata information and any missing

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2017 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.
@@ -51,9 +51,8 @@ public interface CallMetaDataProvider {
* @throws SQLException in case of initialization failure
* @see org.springframework.jdbc.core.simple.SimpleJdbcCall#withoutProcedureColumnMetaDataAccess()
*/
void initializeWithProcedureColumnMetaData(
DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String procedureName)
throws SQLException;
void initializeWithProcedureColumnMetaData(DatabaseMetaData databaseMetaData, String catalogName,
String schemaName, String procedureName) throws SQLException;
/**
* Provide any modification of the procedure name passed in to match the meta data currently used.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2017 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.
@@ -21,8 +21,8 @@ import java.sql.SQLException;
/**
* The Derby specific implementation of the {@link org.springframework.jdbc.core.metadata.TableMetaDataProvider}.
* Overrides the Derby metadata info regarding retreiving generated keys. It seems to work OK so not sure why they
* claim it's not supported.
* Overrides the Derby metadata info regarding retrieving generated keys. It seems to work OK so not sure why
* they claim it's not supported.
*
* @author Thomas Risberg
* @since 3.0
@@ -31,26 +31,26 @@ public class DerbyTableMetaDataProvider extends GenericTableMetaDataProvider {
private boolean supportsGeneratedKeysOverride = false;
public DerbyTableMetaDataProvider(DatabaseMetaData databaseMetaData) throws SQLException {
super(databaseMetaData);
}
@Override
public void initializeWithMetaData(DatabaseMetaData databaseMetaData) throws SQLException {
super.initializeWithMetaData(databaseMetaData);
if (!databaseMetaData.supportsGetGeneratedKeys()) {
logger.warn("Overriding supportsGetGeneratedKeys from DatabaseMetaData to 'true'; it was reported as " +
"'false' by " + databaseMetaData.getDriverName() + " " + databaseMetaData.getDriverVersion());
supportsGeneratedKeysOverride = true;
if (logger.isWarnEnabled()) {
logger.warn("Overriding supportsGetGeneratedKeys from DatabaseMetaData to 'true'; it was reported as " +
"'false' by " + databaseMetaData.getDriverName() + " " + databaseMetaData.getDriverVersion());
}
this.supportsGeneratedKeysOverride = true;
}
}
@Override
public boolean isGetGeneratedKeysSupported() {
boolean derbysAnswer = super.isGetGeneratedKeysSupported();
if (!derbysAnswer) {
return supportsGeneratedKeysOverride;
}
return derbysAnswer;
return (super.isGetGeneratedKeysSupported() || this.supportsGeneratedKeysOverride);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2017 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.
@@ -25,7 +25,7 @@ import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
/**
* Oracle specific implementation for the {@link CallMetaDataProvider} interface.
* Oracle-specific implementation for the {@link CallMetaDataProvider} interface.
* This class is intended for internal use by the Simple JDBC classes.
*
* @author Thomas Risberg
@@ -59,13 +59,13 @@ public class OracleCallMetaDataProvider extends GenericCallMetaDataProvider {
@Override
public String metaDataCatalogNameToUse(String catalogName) {
// Oracle uses catalog name for package name or an empty string if no package
return catalogName == null ? "" : catalogNameToUse(catalogName);
return (catalogName == null ? "" : catalogNameToUse(catalogName));
}
@Override
public String metaDataSchemaNameToUse(String schemaName) {
// Use current user schema if no schema specified
return schemaName == null ? getUserName() : super.metaDataSchemaNameToUse(schemaName);
return (schemaName == null ? getUserName() : super.metaDataSchemaNameToUse(schemaName));
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2017 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.
@@ -25,7 +25,7 @@ import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
/**
* Oracle specific implementation for the {@link org.springframework.jdbc.core.metadata.CallMetaDataProvider} interface.
* Postgres-specific implementation for the {@link CallMetaDataProvider} interface.
* This class is intended for internal use by the Simple JDBC classes.
*
* @author Thomas Risberg
@@ -59,7 +59,7 @@ public class PostgresCallMetaDataProvider extends GenericCallMetaDataProvider {
@Override
public String metaDataSchemaNameToUse(String schemaName) {
// Use public schema if no schema specified
return schemaName == null ? "public" : super.metaDataSchemaNameToUse(schemaName);
return (schemaName == null ? "public" : super.metaDataSchemaNameToUse(schemaName));
}
@Override
@@ -74,7 +74,7 @@ public class PostgresCallMetaDataProvider extends GenericCallMetaDataProvider {
@Override
public boolean byPassReturnParameter(String parameterName) {
return (RETURN_VALUE_NAME.equals(parameterName) ||
super.byPassReturnParameter(parameterName));
return RETURN_VALUE_NAME.equals(parameterName);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2017 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.
@@ -90,8 +90,7 @@ public class SqlParameterSourceUtils {
Map<String, String> caseInsensitiveParameterNames = new HashMap<String, String>();
if (parameterSource instanceof BeanPropertySqlParameterSource) {
String[] propertyNames = ((BeanPropertySqlParameterSource)parameterSource).getReadablePropertyNames();
for (int i = 0; i < propertyNames.length; i++) {
String name = propertyNames[i];
for (String name : propertyNames) {
caseInsensitiveParameterNames.put(name.toLowerCase(), name);
}
}

View File

@@ -229,7 +229,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan
@Override
protected boolean isExistingTransaction(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive());
return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}
/**
@@ -241,7 +241,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan
Connection con = null;
try {
if (txObject.getConnectionHolder() == null ||
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = this.dataSource.getConnection();
if (logger.isDebugEnabled()) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2017 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.
@@ -268,8 +268,10 @@ public abstract class DataSourceUtils {
*/
public static void applyTimeout(Statement stmt, DataSource dataSource, int timeout) throws SQLException {
Assert.notNull(stmt, "No Statement specified");
Assert.notNull(dataSource, "No DataSource specified");
ConnectionHolder holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
ConnectionHolder holder = null;
if (dataSource != null) {
holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
}
if (holder != null && holder.hasTimeout()) {
// Remaining transaction timeout overrides specified value.
stmt.setQueryTimeout(holder.getTimeToLiveInSeconds());

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2017 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.
@@ -54,10 +54,8 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
}
/**
* Set the {@link DatabasePopulator} to execute during the bean initialization
* phase.
* @param databasePopulator the {@code DatabasePopulator} to use during
* initialization
* Set the {@link DatabasePopulator} to execute during the bean initialization phase.
* @param databasePopulator the {@code DatabasePopulator} to use during initialization
* @see #setDatabaseCleaner
*/
public void setDatabasePopulator(DatabasePopulator databasePopulator) {
@@ -84,6 +82,7 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
this.enabled = enabled;
}
/**
* Use the {@linkplain #setDatabasePopulator database populator} to set up
* the database.
@@ -103,7 +102,7 @@ public class DataSourceInitializer implements InitializingBean, DisposableBean {
}
private void execute(DatabasePopulator populator) {
Assert.state(dataSource != null, "DataSource must be set");
Assert.state(this.dataSource != null, "DataSource must be set");
if (this.enabled && populator != null) {
DatabasePopulatorUtils.execute(populator, this.dataSource);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@@ -48,9 +48,7 @@ public abstract class DatabasePopulatorUtils {
populator.populate(connection);
}
finally {
if (connection != null) {
DataSourceUtils.releaseConnection(connection, dataSource);
}
DataSourceUtils.releaseConnection(connection, dataSource);
}
}
catch (Throwable ex) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2017 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.
@@ -32,6 +32,7 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.util.Assert;
/**
* An "RDBMS operation" is a multi-threaded, reusable object representing a query,
@@ -85,27 +86,25 @@ public abstract class RdbmsOperation implements InitializingBean {
/**
* An alternative to the more commonly used setDataSource() when you want to
* use the same JdbcTemplate in multiple RdbmsOperations. This is appropriate if the
* JdbcTemplate has special configuration such as a SQLExceptionTranslator that should
* apply to multiple RdbmsOperation objects.
* An alternative to the more commonly used {@link #setDataSource} when you want to
* use the same {@link JdbcTemplate} in multiple {@code RdbmsOperations}. This is
* appropriate if the {@code JdbcTemplate} has special configuration such as a
* {@link org.springframework.jdbc.support.SQLExceptionTranslator} to be reused.
*/
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
if (jdbcTemplate == null) {
throw new IllegalArgumentException("jdbcTemplate must not be null");
}
Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null");
this.jdbcTemplate = jdbcTemplate;
}
/**
* Return the JdbcTemplate object used by this object.
* Return the {@link JdbcTemplate} used by this operation object.
*/
public JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
}
/**
* Set the JDBC DataSource to obtain connections from.
* Set the JDBC {@link DataSource} to obtain connections from.
* @see org.springframework.jdbc.core.JdbcTemplate#setDataSource
*/
public void setDataSource(DataSource dataSource) {
@@ -233,9 +232,8 @@ public abstract class RdbmsOperation implements InitializingBean {
}
/**
* Subclasses can override this to supply dynamic SQL if they wish,
* but SQL is normally set by calling the setSql() method
* or in a subclass constructor.
* Subclasses can override this to supply dynamic SQL if they wish, but SQL is
* normally set by calling the {@link #setSql} method or in a subclass constructor.
*/
public String getSql() {
return this.sql;
@@ -287,7 +285,7 @@ public abstract class RdbmsOperation implements InitializingBean {
* @param parameters Array containing the declared {@link SqlParameter} objects
* @see #declaredParameters
*/
public void setParameters(SqlParameter[] parameters) {
public void setParameters(SqlParameter... parameters) {
if (isCompiled()) {
throw new InvalidDataAccessApiUsageException("Cannot add parameters once the query is compiled");
}
@@ -396,7 +394,7 @@ public abstract class RdbmsOperation implements InitializingBean {
* Validate the named parameters passed to an execute method based on declared parameters.
* Subclasses should invoke this method before every {@code executeQuery()} or
* {@code update()} method.
* @param parameters parameter Map supplied. May be {@code null}.
* @param parameters parameter Map supplied (may be {@code null})
* @throws InvalidDataAccessApiUsageException if the parameters are invalid
*/
protected void validateNamedParameters(Map<String, ?> parameters) throws InvalidDataAccessApiUsageException {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2017 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.
@@ -70,16 +70,22 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
sql = "";
}
DataAccessException dex = doTranslate(task, sql, ex);
if (dex != null) {
DataAccessException dae = doTranslate(task, sql, ex);
if (dae != null) {
// Specific exception match found.
return dex;
return dae;
}
// Looking for a fallback...
SQLExceptionTranslator fallback = getFallbackTranslator();
if (fallback != null) {
return fallback.translate(task, sql, ex);
dae = fallback.translate(task, sql, ex);
if (dae != null) {
// Fallback exception match found.
return dae;
}
}
// We couldn't identify it more precisely.
return new UncategorizedSQLException(task, sql, ex);
}
@@ -90,7 +96,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
* is allowed to return {@code null} to indicate that no exception match has
* been found and that fallback translation should kick in.
* @param task readable text describing the task being attempted
* @param sql SQL query or update that caused the problem (may be {@code null})
* @param sql SQL query or update that caused the problem (if known)
* @param ex the offending {@code SQLException}
* @return the DataAccessException, wrapping the {@code SQLException};
* or {@code null} if no exception match found
@@ -103,7 +109,7 @@ public abstract class AbstractFallbackSQLExceptionTranslator implements SQLExcep
* <p>To be called by translator subclasses when creating an instance of a generic
* {@link org.springframework.dao.DataAccessException} class.
* @param task readable text describing the task being attempted
* @param sql the SQL statement that caused the problem (may be {@code null})
* @param sql the SQL statement that caused the problem
* @param ex the offending {@code SQLException}
* @return the message {@code String} to use
*/

View File

@@ -472,8 +472,8 @@ public abstract class JdbcUtils {
}
/**
* Convert a column name with underscores to the corresponding property name using "camel case". A name
* like "customer_number" would match a "customerNumber" property name.
* Convert a column name with underscores to the corresponding property name using "camel case".
* A name like "customer_number" would match a "customerNumber" property name.
* @param name the column name to be converted
* @return the name using "camel case"
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@@ -216,9 +216,9 @@ public class SQLErrorCodesFactory {
}
catch (MetaDataAccessException ex) {
logger.warn("Error while extracting database name - falling back to empty error codes", ex);
// Fallback is to return an empty SQLErrorCodes instance.
return new SQLErrorCodes();
}
// Fallback is to return an empty SQLErrorCodes instance.
return new SQLErrorCodes();
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2017 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.
@@ -59,11 +59,15 @@ public class TemporaryLobCreator implements LobCreator {
public void setBlobAsBytes(PreparedStatement ps, int paramIndex, byte[] content)
throws SQLException {
Blob blob = ps.getConnection().createBlob();
blob.setBytes(1, content);
this.temporaryBlobs.add(blob);
ps.setBlob(paramIndex, blob);
if (content != null) {
Blob blob = ps.getConnection().createBlob();
blob.setBytes(1, content);
this.temporaryBlobs.add(blob);
ps.setBlob(paramIndex, blob);
}
else {
ps.setBlob(paramIndex, (Blob) null);
}
if (logger.isDebugEnabled()) {
logger.debug(content != null ? "Copied bytes into temporary BLOB with length " + content.length :
@@ -76,17 +80,21 @@ public class TemporaryLobCreator implements LobCreator {
PreparedStatement ps, int paramIndex, InputStream binaryStream, int contentLength)
throws SQLException {
Blob blob = ps.getConnection().createBlob();
try {
FileCopyUtils.copy(binaryStream, blob.setBinaryStream(1));
if (binaryStream != null) {
Blob blob = ps.getConnection().createBlob();
try {
FileCopyUtils.copy(binaryStream, blob.setBinaryStream(1));
}
catch (IOException ex) {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex);
}
this.temporaryBlobs.add(blob);
ps.setBlob(paramIndex, blob);
}
catch (IOException ex) {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex);
else {
ps.setBlob(paramIndex, (Blob) null);
}
this.temporaryBlobs.add(blob);
ps.setBlob(paramIndex, blob);
if (logger.isDebugEnabled()) {
logger.debug(binaryStream != null ?
"Copied binary stream into temporary BLOB with length " + contentLength :
@@ -98,11 +106,15 @@ public class TemporaryLobCreator implements LobCreator {
public void setClobAsString(PreparedStatement ps, int paramIndex, String content)
throws SQLException {
Clob clob = ps.getConnection().createClob();
clob.setString(1, content);
this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob);
if (content != null) {
Clob clob = ps.getConnection().createClob();
clob.setString(1, content);
this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob);
}
else {
ps.setClob(paramIndex, (Clob) null);
}
if (logger.isDebugEnabled()) {
logger.debug(content != null ? "Copied string into temporary CLOB with length " + content.length() :
@@ -115,17 +127,21 @@ public class TemporaryLobCreator implements LobCreator {
PreparedStatement ps, int paramIndex, InputStream asciiStream, int contentLength)
throws SQLException {
Clob clob = ps.getConnection().createClob();
try {
FileCopyUtils.copy(asciiStream, clob.setAsciiStream(1));
if (asciiStream != null) {
Clob clob = ps.getConnection().createClob();
try {
FileCopyUtils.copy(asciiStream, clob.setAsciiStream(1));
}
catch (IOException ex) {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex);
}
this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob);
}
catch (IOException ex) {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex);
else {
ps.setClob(paramIndex, (Clob) null);
}
this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob);
if (logger.isDebugEnabled()) {
logger.debug(asciiStream != null ?
"Copied ASCII stream into temporary CLOB with length " + contentLength :
@@ -138,17 +154,21 @@ public class TemporaryLobCreator implements LobCreator {
PreparedStatement ps, int paramIndex, Reader characterStream, int contentLength)
throws SQLException {
Clob clob = ps.getConnection().createClob();
try {
FileCopyUtils.copy(characterStream, clob.setCharacterStream(1));
if (characterStream != null) {
Clob clob = ps.getConnection().createClob();
try {
FileCopyUtils.copy(characterStream, clob.setCharacterStream(1));
}
catch (IOException ex) {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex);
}
this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob);
}
catch (IOException ex) {
throw new DataAccessResourceFailureException("Could not copy into LOB stream", ex);
else {
ps.setClob(paramIndex, (Clob) null);
}
this.temporaryClobs.add(clob);
ps.setClob(paramIndex, clob);
if (logger.isDebugEnabled()) {
logger.debug(characterStream != null ?
"Copied character stream into temporary CLOB with length " + contentLength :
@@ -170,4 +190,5 @@ public class TemporaryLobCreator implements LobCreator {
logger.error("Could not free LOB", ex);
}
}
}