Merge branch '3.2.x' into master

Conflicts:
	gradle.properties
	spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java
	spring-context-support/src/main/java/org/springframework/cache/ehcache/EhCacheManagerFactoryBean.java
	spring-core/src/main/java/org/springframework/core/convert/support/StringToEnumConverterFactory.java
	spring-core/src/main/java/org/springframework/core/env/ReadOnlySystemAttributesMap.java
	spring-jdbc/src/main/java/org/springframework/jdbc/datasource/LazyConnectionDataSourceProxy.java
	spring-jdbc/src/main/java/org/springframework/jdbc/support/lob/AbstractLobHandler.java
	spring-web/src/main/java/org/springframework/http/client/BufferingClientHttpRequestWrapper.java
	spring-web/src/main/java/org/springframework/http/client/SimpleBufferingClientHttpRequest.java
	spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java
	spring-web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java
This commit is contained in:
Chris Beams
2013-03-04 15:41:15 +01:00
1450 changed files with 17678 additions and 42998 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -133,7 +133,8 @@ public interface JdbcOperations {
* object via a RowMapper.
* <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
* execute a static query with a PreparedStatement, use the overloaded
* {@code queryForObject} method with {@code null} as argument array.
* {@link #queryForObject(String, RowMapper, Object...)} method with
* {@code null} as argument array.
* @param sql SQL query to execute
* @param rowMapper object that will map one object per row
* @return the single mapped object
@@ -148,7 +149,8 @@ public interface JdbcOperations {
* Execute a query for a result object, given static SQL.
* <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
* execute a static query with a PreparedStatement, use the overloaded
* {@code queryForObject} method with {@code null} as argument array.
* {@link #queryForObject(String, Class, Object...)} method with
* {@code null} as argument array.
* <p>This method is useful for running static SQL with a known outcome.
* The query is expected to be a single row/single column query; the returned
* result will be directly mapped to the corresponding object type.
@@ -166,7 +168,8 @@ public interface JdbcOperations {
* Execute a query for a result Map, given static SQL.
* <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
* execute a static query with a PreparedStatement, use the overloaded
* {@code queryForMap} method with {@code null} as argument array.
* {@link #queryForMap(String, Object...)} method with {@code null}
* as argument array.
* <p>The query is expected to be a single row query; the result row will be
* mapped to a Map (one entry for each column, using the column name as the key).
* @param sql SQL query to execute
@@ -194,7 +197,9 @@ public interface JdbcOperations {
* exactly one row, or does not return exactly one column in that row
* @throws DataAccessException if there is any problem executing the query
* @see #queryForLong(String, Object[])
* @deprecated in favor of {@link #queryForObject(String, Class)}
*/
@Deprecated
long queryForLong(String sql) throws DataAccessException;
/**
@@ -211,7 +216,9 @@ public interface JdbcOperations {
* exactly one row, or does not return exactly one column in that row
* @throws DataAccessException if there is any problem executing the query
* @see #queryForInt(String, Object[])
* @deprecated in favor of {@link #queryForObject(String, Class)}
*/
@Deprecated
int queryForInt(String sql) throws DataAccessException;
/**
@@ -712,7 +719,9 @@ public interface JdbcOperations {
* @throws DataAccessException if the query fails
* @see #queryForLong(String)
* @see java.sql.Types
* @deprecated in favor of {@link #queryForObject(String, Object[], int[], Class)} )}
*/
@Deprecated
long queryForLong(String sql, Object[] args, int[] argTypes) throws DataAccessException;
/**
@@ -730,7 +739,9 @@ public interface JdbcOperations {
* exactly one row, or does not return exactly one column in that row
* @throws DataAccessException if the query fails
* @see #queryForLong(String)
* @deprecated in favor of {@link #queryForObject(String, Class, Object[])} )}
*/
@Deprecated
long queryForLong(String sql, Object... args) throws DataAccessException;
/**
@@ -748,7 +759,9 @@ public interface JdbcOperations {
* @throws DataAccessException if the query fails
* @see #queryForInt(String)
* @see java.sql.Types
* @deprecated in favor of {@link #queryForObject(String, Object[], int[], Class)} )}
*/
@Deprecated
int queryForInt(String sql, Object[] args, int[] argTypes) throws DataAccessException;
/**
@@ -766,7 +779,9 @@ public interface JdbcOperations {
* exactly one row, or does not return exactly one column in that row
* @throws DataAccessException if the query fails
* @see #queryForInt(String)
* @deprecated in favor of {@link #queryForObject(String, Class, Object[])} )}
*/
@Deprecated
int queryForInt(String sql, Object... args) throws DataAccessException;
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -477,11 +477,13 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
return queryForObject(sql, getSingleColumnRowMapper(requiredType));
}
@Deprecated
public long queryForLong(String sql) throws DataAccessException {
Number number = queryForObject(sql, Long.class);
return (number != null ? number.longValue() : 0);
}
@Deprecated
public int queryForInt(String sql) throws DataAccessException {
Number number = queryForObject(sql, Integer.class);
return (number != null ? number.intValue() : 0);
@@ -757,21 +759,25 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
return queryForObject(sql, args, getColumnMapRowMapper());
}
@Deprecated
public long queryForLong(String sql, Object[] args, int[] argTypes) throws DataAccessException {
Number number = queryForObject(sql, args, argTypes, Long.class);
return (number != null ? number.longValue() : 0);
}
@Deprecated
public long queryForLong(String sql, Object... args) throws DataAccessException {
Number number = queryForObject(sql, args, Long.class);
return (number != null ? number.longValue() : 0);
}
@Deprecated
public int queryForInt(String sql, Object[] args, int[] argTypes) throws DataAccessException {
Number number = queryForObject(sql, args, argTypes, Integer.class);
return (number != null ? number.intValue() : 0);
}
@Deprecated
public int queryForInt(String sql, Object... args) throws DataAccessException {
Number number = queryForObject(sql, args, Integer.class);
return (number != null ? number.intValue() : 0);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -146,7 +146,7 @@ public class PreparedStatementCreatorFactory {
* Return a new PreparedStatementSetter for the given parameters.
* @param params list of parameters (may be {@code null})
*/
public PreparedStatementSetter newPreparedStatementSetter(List params) {
public PreparedStatementSetter newPreparedStatementSetter(List<?> params) {
return new PreparedStatementCreatorImpl(params != null ? params : Collections.emptyList());
}
@@ -225,7 +225,7 @@ public class PreparedStatementCreatorFactory {
}
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = null;
PreparedStatement ps;
if (generatedKeysColumnNames != null || returnGeneratedKeys) {
try {
if (generatedKeysColumnNames != null) {
@@ -235,10 +235,10 @@ public class PreparedStatementCreatorFactory {
ps = con.prepareStatement(this.actualSql, PreparedStatement.RETURN_GENERATED_KEYS);
}
}
catch (AbstractMethodError ex) {
catch (AbstractMethodError err) {
throw new InvalidDataAccessResourceUsageException(
"The JDBC driver is not compliant to JDBC 3.0 and thus " +
"does not support retrieval of auto-generated keys", ex);
"Your JDBC driver is not compliant with JDBC 3.0 - " +
"it does not support retrieval of auto-generated keys", err);
}
}
else if (resultSetType == ResultSet.TYPE_FORWARD_ONLY && !updatableResults) {
@@ -263,7 +263,7 @@ public class PreparedStatementCreatorFactory {
int sqlColIndx = 1;
for (int i = 0; i < this.parameters.size(); i++) {
Object in = this.parameters.get(i);
SqlParameter declaredParameter = null;
SqlParameter declaredParameter;
// SqlParameterValue overrides declared parameter metadata, in particular for
// independence from the declared parameter position in case of named parameters.
if (in instanceof SqlParameterValue) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -22,6 +22,7 @@ import java.math.BigInteger;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.DatabaseMetaData;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
@@ -189,7 +190,7 @@ public abstract class StatementCreatorUtils {
if (inValue instanceof SqlParameterValue) {
SqlParameterValue parameterValue = (SqlParameterValue) inValue;
if (logger.isDebugEnabled()) {
logger.debug("Overriding typeinfo with runtime info from SqlParameterValue: column index " + paramIndex +
logger.debug("Overriding type info with runtime info from SqlParameterValue: column index " + paramIndex +
", SQL type " + parameterValue.getSqlType() +
", Type name " + parameterValue.getTypeName());
}
@@ -228,18 +229,31 @@ public abstract class StatementCreatorUtils {
boolean useSetObject = false;
sqlType = Types.NULL;
try {
DatabaseMetaData dbmd = ps.getConnection().getMetaData();
String databaseProductName = dbmd.getDatabaseProductName();
String jdbcDriverName = dbmd.getDriverName();
if (databaseProductName.startsWith("Informix") ||
jdbcDriverName.startsWith("Microsoft SQL Server")) {
useSetObject = true;
ParameterMetaData pmd = null;
try {
pmd = ps.getParameterMetaData();
}
else if (databaseProductName.startsWith("DB2") ||
jdbcDriverName.startsWith("jConnect") ||
jdbcDriverName.startsWith("SQLServer")||
jdbcDriverName.startsWith("Apache Derby")) {
sqlType = Types.VARCHAR;
catch (Throwable ex) {
// JDBC driver not compliant with JDBC 3.0
// -> proceed with database-specific checks
}
if (pmd != null) {
sqlType = pmd.getParameterType(paramIndex);
}
else {
DatabaseMetaData dbmd = ps.getConnection().getMetaData();
String databaseProductName = dbmd.getDatabaseProductName();
String jdbcDriverName = dbmd.getDriverName();
if (databaseProductName.startsWith("Informix") ||
jdbcDriverName.startsWith("Microsoft SQL Server")) {
useSetObject = true;
}
else if (databaseProductName.startsWith("DB2") ||
jdbcDriverName.startsWith("jConnect") ||
jdbcDriverName.startsWith("SQLServer")||
jdbcDriverName.startsWith("Apache Derby")) {
sqlType = Types.VARCHAR;
}
}
}
catch (Throwable ex) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2010 the original author or authors.
* Copyright 2002-2013 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.
@@ -56,33 +56,33 @@ public interface CallMetaDataProvider {
/**
* Provide any modification of the procedure name passed in to match the meta data currently used.
* This could include alterig the case.
* This could include altering the case.
*/
String procedureNameToUse(String procedureName);
/**
* Provide any modification of the catalog name passed in to match the meta data currently used.
* This could include alterig the case.
* This could include altering the case.
*/
String catalogNameToUse(String catalogName);
/**
* Provide any modification of the schema name passed in to match the meta data currently used.
* This could include alterig the case.
* This could include altering the case.
*/
String schemaNameToUse(String schemaName);
/**
* Provide any modification of the catalog name passed in to match the meta data currently used.
* The reyurned value will be used for meta data lookups. This could include alterig the case used
* or providing a base catalog if mone provided.
* The returned value will be used for meta data lookups. This could include altering the case used
* or providing a base catalog if none is provided.
*/
String metaDataCatalogNameToUse(String catalogName) ;
/**
* Provide any modification of the schema name passed in to match the meta data currently used.
* The reyurned value will be used for meta data lookups. This could include alterig the case used
* or providing a base schema if mone provided.
* The returned value will be used for meta data lookups. This could include altering the case used
* or providing a base schema if none is provided.
*/
String metaDataSchemaNameToUse(String schemaName) ;

View File

@@ -75,4 +75,4 @@ public class CallParameterMetaData {
public boolean isNullable() {
return nullable;
}
}
}

View File

@@ -53,4 +53,4 @@ public class DerbyTableMetaDataProvider extends GenericTableMetaDataProvider {
}
return derbysAnswer;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -310,7 +310,6 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
tmd.setCatalogName(tables.getString("TABLE_CAT"));
tmd.setSchemaName(tables.getString("TABLE_SCHEM"));
tmd.setTableName(tables.getString("TABLE_NAME"));
tmd.setType(tables.getString("TABLE_TYPE"));
if (tmd.getSchemaName() == null) {
tableMeta.put(userName != null ? userName.toUpperCase() : "", tmd);
}
@@ -445,7 +444,6 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
private String tableName;
private String type;
public void setCatalogName(String catalogName) {
this.catalogName = catalogName;
@@ -470,14 +468,6 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
public String getTableName() {
return this.tableName;
}
public void setType(String type) {
this.type = type;
}
public String getType() {
return this.type;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -76,8 +76,8 @@ public interface TableMetaDataProvider {
/**
* Provide any modification of the catalog name passed in to match the meta data currently used.
* The reyurned value will be used for meta data lookups. This could include alterig the case used or
* providing a base catalog if mone provided.
* The returned value will be used for meta data lookups. This could include altering the case used or
* providing a base catalog if none is provided.
*
* @param catalogName
* @return catalog name to use
@@ -86,8 +86,8 @@ public interface TableMetaDataProvider {
/**
* Provide any modification of the schema name passed in to match the meta data currently used.
* The reyurned value will be used for meta data lookups. This could include alterig the case used or
* providing a base schema if mone provided.
* The returned value will be used for meta data lookups. This could include altering the case used or
* providing a base schema if none is provided.
*
* @param schemaName
* @return schema name to use

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2002-2013 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.core.namedparam;
/**
* A simple empty implementation of the {@link SqlParameterSource} interface.
*
* @author Juergen Hoeller
* @since 3.2.2
*/
public class EmptySqlParameterSource implements SqlParameterSource {
/**
* A shared instance of {@link EmptySqlParameterSource}.
*/
public static final EmptySqlParameterSource INSTANCE = new EmptySqlParameterSource();
public boolean hasValue(String paramName) {
return false;
}
public Object getValue(String paramName) throws IllegalArgumentException {
throw new IllegalArgumentException("This SqlParameterSource is empty");
}
public int getSqlType(String paramName) {
return TYPE_UNKNOWN;
}
public String getTypeName(String paramName) {
return null;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -88,6 +88,21 @@ public interface NamedParameterJdbcOperations {
<T> T execute(String sql, Map<String, ?> paramMap, PreparedStatementCallback<T> action)
throws DataAccessException;
/**
* Execute a JDBC data access operation, implemented as callback action
* working on a JDBC PreparedStatement. This allows for implementing arbitrary
* data access operations on a single Statement, within Spring's managed
* JDBC environment: that is, participating in Spring-managed transactions
* and converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
* <p>The callback action can return a result object, for example a
* domain object or a collection of domain objects.
* @param sql SQL to execute
* @param action callback object that specifies the action
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException if there is any problem
*/
<T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a list
* of arguments to bind to the query, reading the ResultSet with a
@@ -115,6 +130,19 @@ public interface NamedParameterJdbcOperations {
<T> T query(String sql, Map<String, ?> paramMap, ResultSetExtractor<T> rse)
throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL,
* reading the ResultSet with a ResultSetExtractor.
* <p>Note: In contrast to the JdbcOperations method with the same signature,
* this query variant always uses a PreparedStatement. It is effectively
* equivalent to a query call with an empty parameter Map.
* @param sql SQL query to execute
* @param rse object that will extract results
* @return an arbitrary result object, as returned by the ResultSetExtractor
* @throws org.springframework.dao.DataAccessException if the query fails
*/
<T> T query(String sql, ResultSetExtractor<T> rse) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a list of
* arguments to bind to the query, reading the ResultSet on a per-row basis
@@ -139,6 +167,18 @@ public interface NamedParameterJdbcOperations {
*/
void query(String sql, Map<String, ?> paramMap, RowCallbackHandler rch) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL,
* reading the ResultSet on a per-row basis with a RowCallbackHandler.
* <p>Note: In contrast to the JdbcOperations method with the same signature,
* this query variant always uses a PreparedStatement. It is effectively
* equivalent to a query call with an empty parameter Map.
* @param sql SQL query to execute
* @param rch object that will extract results, one row at a time
* @throws org.springframework.dao.DataAccessException if the query fails
*/
void query(String sql, RowCallbackHandler rch) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a list
* of arguments to bind to the query, mapping each row to a Java object
@@ -166,6 +206,19 @@ public interface NamedParameterJdbcOperations {
<T> List<T> query(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper)
throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL,
* mapping each row to a Java object via a RowMapper.
* <p>Note: In contrast to the JdbcOperations method with the same signature,
* this query variant always uses a PreparedStatement. It is effectively
* equivalent to a query call with an empty parameter Map.
* @param sql SQL query to execute
* @param rowMapper object that will map one object per row
* @return the result List, containing mapped objects
* @throws org.springframework.dao.DataAccessException if the query fails
*/
<T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException;
/**
* Query given SQL to create a prepared statement from SQL and a list
* of arguments to bind to the query, mapping a single result row to a
@@ -245,8 +298,7 @@ public interface NamedParameterJdbcOperations {
* @param paramSource container of arguments to bind to the query
* @return the result Map (one entry for each column, using the column name as the key)
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
* if the query does not return exactly one row, or does not return exactly
* one column in that row
* if the query does not return exactly one row
* @throws org.springframework.dao.DataAccessException if the query fails
* @see org.springframework.jdbc.core.JdbcTemplate#queryForMap(String)
* @see org.springframework.jdbc.core.ColumnMapRowMapper
@@ -266,8 +318,7 @@ public interface NamedParameterJdbcOperations {
* (leaving it to the PreparedStatement to guess the corresponding SQL type)
* @return the result Map (one entry for each column, using the column name as the key)
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
* if the query does not return exactly one row, or does not return exactly
* one column in that row
* if the query does not return exactly one row
* @throws org.springframework.dao.DataAccessException if the query fails
* @see org.springframework.jdbc.core.JdbcTemplate#queryForMap(String)
* @see org.springframework.jdbc.core.ColumnMapRowMapper
@@ -287,7 +338,9 @@ public interface NamedParameterJdbcOperations {
* one column in that row
* @throws org.springframework.dao.DataAccessException if the query fails
* @see org.springframework.jdbc.core.JdbcTemplate#queryForLong(String)
* @deprecated in favor of {@link #queryForObject(String, SqlParameterSource, Class)}
*/
@Deprecated
long queryForLong(String sql, SqlParameterSource paramSource) throws DataAccessException;
/**
@@ -304,7 +357,9 @@ public interface NamedParameterJdbcOperations {
* one column in that row
* @throws org.springframework.dao.DataAccessException if the query fails
* @see org.springframework.jdbc.core.JdbcTemplate#queryForLong(String)
* @deprecated in favor of {@link #queryForObject(String, Map, Class)}
*/
@Deprecated
long queryForLong(String sql, Map<String, ?> paramMap) throws DataAccessException;
/**
@@ -319,7 +374,9 @@ public interface NamedParameterJdbcOperations {
* exactly one row, or does not return exactly one column in that row
* @throws org.springframework.dao.DataAccessException if the query fails
* @see org.springframework.jdbc.core.JdbcTemplate#queryForInt(String)
* @deprecated in favor of {@link #queryForObject(String, SqlParameterSource, Class)}
*/
@Deprecated
int queryForInt(String sql, SqlParameterSource paramSource) throws DataAccessException;
/**
@@ -335,7 +392,9 @@ public interface NamedParameterJdbcOperations {
* exactly one row, or does not return exactly one column in that row
* @throws org.springframework.dao.DataAccessException if the query fails
* @see org.springframework.jdbc.core.JdbcTemplate#queryForInt(String)
* @deprecated in favor of {@link #queryForObject(String, Map, Class)}
*/
@Deprecated
int queryForInt(String sql, Map<String, ?> paramMap) throws DataAccessException;
/**
@@ -378,8 +437,8 @@ public interface NamedParameterJdbcOperations {
* list of arguments to bind to the query, expecting a result list.
* <p>The results will be mapped to a List (one entry for each row) of
* Maps (one entry for each column, using the column name as the key).
* Thus Each element in the list will be of the form returned by this interface's
* queryForMap() methods.
* Each element in the list will be of the form returned by this interface's
* {@code queryForMap} methods.
* @param sql SQL query to execute
* @param paramSource container of arguments to bind to the query
* @return a List that contains a Map per row
@@ -394,7 +453,7 @@ public interface NamedParameterJdbcOperations {
* <p>The results will be mapped to a List (one entry for each row) of
* Maps (one entry for each column, using the column name as the key).
* Each element in the list will be of the form returned by this interface's
* queryForMap() methods.
* {@code queryForMap} methods.
* @param sql SQL query to execute
* @param paramMap map of parameters to bind to the query
* (leaving it to the PreparedStatement to guess the corresponding SQL type)
@@ -499,7 +558,7 @@ public interface NamedParameterJdbcOperations {
* @param batchValues the array of Maps containing the batch of arguments for the query
* @return an array containing the numbers of rows affected by each update in the batch
*/
public int[] batchUpdate(String sql, Map<String, ?>[] batchValues);
int[] batchUpdate(String sql, Map<String, ?>[] batchValues);
/**
* Execute a batch using the supplied SQL statement with the batch of supplied arguments.
@@ -507,6 +566,6 @@ public interface NamedParameterJdbcOperations {
* @param batchArgs the array of {@link SqlParameterSource} containing the batch of arguments for the query
* @return an array containing the numbers of rows affected by each update in the batch
*/
public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs);
int[] batchUpdate(String sql, SqlParameterSource[] batchArgs);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -137,6 +137,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
return execute(sql, new MapSqlParameterSource(paramMap), action);
}
public <T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException {
return execute(sql, EmptySqlParameterSource.INSTANCE, action);
}
public <T> T query(String sql, SqlParameterSource paramSource, ResultSetExtractor<T> rse)
throws DataAccessException {
@@ -149,6 +153,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
return query(sql, new MapSqlParameterSource(paramMap), rse);
}
public <T> T query(String sql, ResultSetExtractor<T> rse) throws DataAccessException {
return query(sql, EmptySqlParameterSource.INSTANCE, rse);
}
public void query(String sql, SqlParameterSource paramSource, RowCallbackHandler rch)
throws DataAccessException {
@@ -161,6 +169,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
query(sql, new MapSqlParameterSource(paramMap), rch);
}
public void query(String sql, RowCallbackHandler rch) throws DataAccessException {
query(sql, EmptySqlParameterSource.INSTANCE, rch);
}
public <T> List<T> query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
throws DataAccessException {
@@ -173,6 +185,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
return query(sql, new MapSqlParameterSource(paramMap), rowMapper);
}
public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException {
return query(sql, EmptySqlParameterSource.INSTANCE, rowMapper);
}
public <T> T queryForObject(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
throws DataAccessException {
@@ -206,20 +222,24 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
return queryForObject(sql, paramMap, new ColumnMapRowMapper());
}
@Deprecated
public long queryForLong(String sql, SqlParameterSource paramSource) throws DataAccessException {
Number number = queryForObject(sql, paramSource, Long.class);
return (number != null ? number.longValue() : 0);
}
@Deprecated
public long queryForLong(String sql, Map<String, ?> paramMap) throws DataAccessException {
return queryForLong(sql, new MapSqlParameterSource(paramMap));
}
@Deprecated
public int queryForInt(String sql, SqlParameterSource paramSource) throws DataAccessException {
Number number = queryForObject(sql, paramSource, Integer.class);
return (number != null ? number.intValue() : 0);
}
@Deprecated
public int queryForInt(String sql, Map<String, ?> paramMap) throws DataAccessException {
return queryForInt(sql, new MapSqlParameterSource(paramMap));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -97,7 +97,7 @@ public abstract class AbstractJdbcCall {
/**
* Get the configured {@link JdbcTemplate}
* Get the configured {@link JdbcTemplate}.
*/
public JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
@@ -110,7 +110,6 @@ public abstract class AbstractJdbcCall {
return this.callableStatementFactory;
}
/**
* Set the name of the stored procedure.
*/
@@ -294,7 +293,7 @@ public abstract class AbstractJdbcCall {
this.callMetaDataContext.createReturnResultSetParameter(entry.getKey(), entry.getValue());
this.declaredParameters.add(resultSetParameter);
}
callMetaDataContext.processParameters(this.declaredParameters);
this.callMetaDataContext.processParameters(this.declaredParameters);
this.callString = this.callMetaDataContext.createCallString();
if (logger.isDebugEnabled()) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -74,9 +74,9 @@ public abstract class AbstractJdbcInsert {
private final List<String> declaredColumns = new ArrayList<String>();
/**
* Has this operation been compiled? Compilation means at
* least checking that a DataSource or JdbcTemplate has been provided,
* but subclasses may also implement their own custom validation.
* Has this operation been compiled? Compilation means at least checking
* that a DataSource or JdbcTemplate has been provided, but subclasses
* may also implement their own custom validation.
*/
private boolean compiled = false;
@@ -108,9 +108,16 @@ public abstract class AbstractJdbcInsert {
//-------------------------------------------------------------------------
// Methods dealing with configuaration properties
// Methods dealing with configuration properties
//-------------------------------------------------------------------------
/**
* Get the {@link JdbcTemplate} that is configured to be used.
*/
public JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
}
/**
* Set the name of the table for this insert
*/
@@ -230,41 +237,31 @@ public abstract class AbstractJdbcInsert {
return this.insertTypes;
}
/**
* Get the {@link JdbcTemplate} that is configured to be used
*/
protected JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
}
//-------------------------------------------------------------------------
// Methods handling compilation issues
//-------------------------------------------------------------------------
/**
* Compile this JdbcInsert using provided parameters and meta data plus other settings. This
* finalizes the configuration for this object and subsequent attempts to compile are ignored.
* This will be implicitly called the first time an un-compiled insert is executed.
* @throws org.springframework.dao.InvalidDataAccessApiUsageException if the object hasn't
* been correctly initialized, for example if no DataSource has been provided
* Compile this JdbcInsert using provided parameters and meta data plus other settings.
* This finalizes the configuration for this object and subsequent attempts to compile are
* ignored. This will be implicitly called the first time an un-compiled insert is executed.
* @throws InvalidDataAccessApiUsageException if the object hasn't been correctly initialized,
* for example if no DataSource has been provided
*/
public synchronized final void compile() throws InvalidDataAccessApiUsageException {
if (!isCompiled()) {
if (getTableName() == null) {
throw new InvalidDataAccessApiUsageException("Table name is required");
}
try {
this.jdbcTemplate.afterPropertiesSet();
}
catch (IllegalArgumentException ex) {
throw new InvalidDataAccessApiUsageException(ex.getMessage());
}
compileInternal();
this.compiled = true;
if (logger.isDebugEnabled()) {
logger.debug("JdbcInsert for table [" + getTableName() + "] compiled");
}
@@ -272,21 +269,17 @@ public abstract class AbstractJdbcInsert {
}
/**
* Method to perform the actual compilation. Subclasses can override this template method to perform
* their own compilation. Invoked after this base class's compilation is complete.
* Method to perform the actual compilation. Subclasses can override this template method
* to perform their own compilation. Invoked after this base class's compilation is complete.
*/
protected void compileInternal() {
tableMetaDataContext.processMetaData(getJdbcTemplate().getDataSource(), getColumnNames(), getGeneratedKeyNames());
insertString = tableMetaDataContext.createInsertString(getGeneratedKeyNames());
insertTypes = tableMetaDataContext.createInsertTypes();
this.tableMetaDataContext.processMetaData(
getJdbcTemplate().getDataSource(), getColumnNames(), getGeneratedKeyNames());
this.insertString = this.tableMetaDataContext.createInsertString(getGeneratedKeyNames());
this.insertTypes = this.tableMetaDataContext.createInsertTypes();
if (logger.isDebugEnabled()) {
logger.debug("Compiled JdbcInsert. Insert string is [" + getInsertString() + "]");
logger.debug("Compiled insert object: insert string is [" + getInsertString() + "]");
}
onCompileInternal();
}
@@ -318,12 +311,13 @@ public abstract class AbstractJdbcInsert {
}
/**
* Method to check whether we are allowd to make any configuration changes at this time. If the class has been
* compiled, then no further changes to the configuration are allowed.
* Method to check whether we are allowd to make any configuration changes at this time.
* If the class has been compiled, then no further changes to the configuration are allowed.
*/
protected void checkIfConfigurationModificationIsAllowed() {
if (isCompiled()) {
throw new InvalidDataAccessApiUsageException("Configuration can't be altered once the class has been compiled or used.");
throw new InvalidDataAccessApiUsageException(
"Configuration can't be altered once the class has been compiled or used");
}
}
@@ -334,7 +328,6 @@ public abstract class AbstractJdbcInsert {
/**
* Method that provides execution of the insert using the passed in Map of parameters
*
* @param args Map with parameter names and values to be used in insert
* @return number of rows affected
*/
@@ -346,7 +339,6 @@ public abstract class AbstractJdbcInsert {
/**
* Method that provides execution of the insert using the passed in {@link SqlParameterSource}
*
* @param parameterSource parameter names and values to be used in insert
* @return number of rows affected
*/
@@ -357,14 +349,13 @@ public abstract class AbstractJdbcInsert {
}
/**
* Method to execute the insert
* Method to execute the insert.
*/
private int executeInsertInternal(List<Object> values) {
if (logger.isDebugEnabled()) {
logger.debug("The following parameters are used for insert " + getInsertString() + " with: " + values);
}
int updateCount = jdbcTemplate.update(getInsertString(), values.toArray(), getInsertTypes());
return updateCount;
return getJdbcTemplate().update(getInsertString(), values.toArray(), getInsertTypes());
}
/**
@@ -428,8 +419,8 @@ public abstract class AbstractJdbcInsert {
return kh.getKey();
}
else {
throw new DataIntegrityViolationException("Unable to retrieve the generated key for the insert: " +
getInsertString());
throw new DataIntegrityViolationException(
"Unable to retrieve the generated key for the insert: " + getInsertString());
}
}
@@ -442,7 +433,7 @@ public abstract class AbstractJdbcInsert {
}
final KeyHolder keyHolder = new GeneratedKeyHolder();
if (this.tableMetaDataContext.isGetGeneratedKeysSupported()) {
jdbcTemplate.update(
getJdbcTemplate().update(
new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = prepareStatementForGeneratedKeys(con);
@@ -467,22 +458,20 @@ public abstract class AbstractJdbcInsert {
getGeneratedKeyNames().length + " columns specified: " + Arrays.asList(getGeneratedKeyNames()));
}
// This is a hack to be able to get the generated key from a database that doesn't support
// get generated keys feature. HSQL is one, PostgreSQL is another. Postgres uses a RETURNING
// get generated keys feature. HSQL is one, PostgreSQL is another. Postgres uses a RETURNING
// clause while HSQL uses a second query that has to be executed with the same connection.
final String keyQuery = tableMetaDataContext.getSimulationQueryForGetGeneratedKey(
tableMetaDataContext.getTableName(),
getGeneratedKeyNames()[0]);
final String keyQuery = this.tableMetaDataContext.getSimulationQueryForGetGeneratedKey(
this.tableMetaDataContext.getTableName(), getGeneratedKeyNames()[0]);
Assert.notNull(keyQuery, "Query for simulating get generated keys can't be null");
if (keyQuery.toUpperCase().startsWith("RETURNING")) {
Long key = jdbcTemplate.queryForLong(
getInsertString() + " " + keyQuery,
values.toArray(new Object[values.size()]));
HashMap keys = new HashMap(1);
Long key = getJdbcTemplate().queryForObject(getInsertString() + " " + keyQuery,
values.toArray(new Object[values.size()]), Long.class);
Map<String, Object> keys = new HashMap<String, Object>(1);
keys.put(getGeneratedKeyNames()[0], key);
keyHolder.getKeyList().add(keys);
}
else {
jdbcTemplate.execute(new ConnectionCallback() {
getJdbcTemplate().execute(new ConnectionCallback<Object>() {
public Object doInConnection(Connection con) throws SQLException, DataAccessException {
// Do the insert
PreparedStatement ps = null;
@@ -490,13 +479,14 @@ public abstract class AbstractJdbcInsert {
ps = con.prepareStatement(getInsertString());
setParameterValues(ps, values, getInsertTypes());
ps.executeUpdate();
} finally {
}
finally {
JdbcUtils.closeStatement(ps);
}
//Get the key
Statement keyStmt = null;
ResultSet rs = null;
HashMap keys = new HashMap(1);
Map<String, Object> keys = new HashMap<String, Object>(1);
try {
keyStmt = con.createStatement();
rs = keyStmt.executeQuery(keyQuery);
@@ -505,7 +495,8 @@ public abstract class AbstractJdbcInsert {
keys.put(getGeneratedKeyNames()[0], key);
keyHolder.getKeyList().add(keys);
}
} finally {
}
finally {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(keyStmt);
}
@@ -547,14 +538,14 @@ public abstract class AbstractJdbcInsert {
}
/**
* Method that provides execution of a batch insert using the passed in Maps of parameters
*
* Method that provides execution of a batch insert using the passed in Maps of parameters.
* @param batch array of Maps with parameter names and values to be used in batch insert
* @return array of number of rows affected
*/
@SuppressWarnings("unchecked")
protected int[] doExecuteBatch(Map<String, Object>[] batch) {
checkCompiled();
List[] batchValues = new ArrayList[batch.length];
List<Object>[] batchValues = new ArrayList[batch.length];
int i = 0;
for (Map<String, Object> args : batch) {
List<Object> values = matchInParameterValuesWithInsertColumns(args);
@@ -565,13 +556,13 @@ public abstract class AbstractJdbcInsert {
/**
* Method that provides execution of a batch insert using the passed in array of {@link SqlParameterSource}
*
* @param batch array of SqlParameterSource with parameter names and values to be used in insert
* @return array of number of rows affected
*/
@SuppressWarnings("unchecked")
protected int[] doExecuteBatch(SqlParameterSource[] batch) {
checkCompiled();
List[] batchValues = new ArrayList[batch.length];
List<Object>[] batchValues = new ArrayList[batch.length];
int i = 0;
for (SqlParameterSource parameterSource : batch) {
List<Object> values = matchInParameterValuesWithInsertColumns(parameterSource);
@@ -581,27 +572,22 @@ public abstract class AbstractJdbcInsert {
}
/**
* Method to execute the batch insert
* Method to execute the batch insert.
*/
//TODO synchronize parameter setters with the SimpleJdbcTemplate
private int[] executeBatchInternal(final List<Object>[] batchValues) {
if (logger.isDebugEnabled()) {
logger.debug("Executing statement " + getInsertString() + " with batch of size: " + batchValues.length);
}
int[] updateCounts = jdbcTemplate.batchUpdate(
getInsertString(),
return getJdbcTemplate().batchUpdate(getInsertString(),
new BatchPreparedStatementSetter() {
public void setValues(PreparedStatement ps, int i) throws SQLException {
List<Object> values = batchValues[i];
setParameterValues(ps, values, getInsertTypes());
}
public int getBatchSize() {
return batchValues.length;
}
});
return updateCounts;
}
/**
@@ -611,6 +597,7 @@ public abstract class AbstractJdbcInsert {
*/
private void setParameterValues(PreparedStatement preparedStatement, List<Object> values, int[] columnTypes)
throws SQLException {
int colIndex = 0;
for (Object value : values) {
colIndex++;
@@ -624,25 +611,23 @@ public abstract class AbstractJdbcInsert {
}
/**
* Match the provided in parameter values with regitered parameters and parameters defined via metedata
* processing.
*
* Match the provided in parameter values with regitered parameters and parameters defined
* via metadata processing.
* @param parameterSource the parameter vakues provided as a {@link SqlParameterSource}
* @return Map with parameter names and values
*/
protected List<Object> matchInParameterValuesWithInsertColumns(SqlParameterSource parameterSource) {
return tableMetaDataContext.matchInParameterValuesWithInsertColumns(parameterSource);
return this.tableMetaDataContext.matchInParameterValuesWithInsertColumns(parameterSource);
}
/**
* Match the provided in parameter values with regitered parameters and parameters defined via metedata
* processing.
*
* Match the provided in parameter values with regitered parameters and parameters defined
* via metadata processing.
* @param args the parameter values provided in a Map
* @return Map with parameter names and values
*/
protected List<Object> matchInParameterValuesWithInsertColumns(Map<String, Object> args) {
return tableMetaDataContext.matchInParameterValuesWithInsertColumns(args);
return this.tableMetaDataContext.matchInParameterValuesWithInsertColumns(args);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -128,7 +128,7 @@ public class SimpleJdbcCall extends AbstractJdbcCall implements SimpleJdbcCallOp
/**
* @deprecated in favor of {@link #returningResultSet(String, org.springframework.jdbc.core.RowMapper)}
*/
@Deprecated
@Deprecated
public SimpleJdbcCall returningResultSet(String parameterName, ParameterizedRowMapper rowMapper) {
addDeclaredRowMapper(parameterName, rowMapper);
return this;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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,9 +33,9 @@ import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
* name of the table and a Map containing the column names and the column values.
*
* <p>The meta data processing is based on the DatabaseMetaData provided by the
* JDBC driver. As long as the JBDC driver can provide the names of the columns
* JDBC driver. As long as the JBDC driver can provide the names of the columns
* for a specified table than we can rely on this auto-detection feature. If that
* is not the case then the column names must be specified explicitly.
* is not the case, then the column names must be specified explicitly.
*
* <p>The actual insert is being handled using Spring's
* {@link org.springframework.jdbc.core.JdbcTemplate}.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -23,15 +23,16 @@ import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.support.lob.LobCreator;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.util.Assert;
/**
* Abstract PreparedStatementCallback implementation that manages a LobCreator.
* Abstract {@link PreparedStatementCallback} implementation that manages a {@link LobCreator}.
* Typically used as inner class, with access to surrounding method arguments.
*
* <p>Delegates to the {@code setValues} template method for setting values
* on the PreparedStatement, using a given LobCreator for BLOB/CLOB arguments.
*
* <p>A usage example with JdbcTemplate:
* <p>A usage example with {@link org.springframework.jdbc.core.JdbcTemplate}:
*
* <pre class="code">JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // reusable object
* LobHandler lobHandler = new DefaultLobHandler(); // reusable object
@@ -62,6 +63,7 @@ public abstract class AbstractLobCreatingPreparedStatementCallback implements Pr
* @param lobHandler the LobHandler to create LobCreators with
*/
public AbstractLobCreatingPreparedStatementCallback(LobHandler lobHandler) {
Assert.notNull(lobHandler, "LobHandler must not be null");
this.lobHandler = lobHandler;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -139,14 +139,18 @@ public abstract class AbstractDriverBasedDataSource extends AbstractDataSource {
* @see java.sql.Driver#connect(String, java.util.Properties)
*/
protected Connection getConnectionFromDriver(String username, String password) throws SQLException {
Properties props = new Properties(getConnectionProperties());
Properties mergedProps = new Properties();
Properties connProps = getConnectionProperties();
if (connProps != null) {
mergedProps.putAll(connProps);
}
if (username != null) {
props.setProperty("user", username);
mergedProps.setProperty("user", username);
}
if (password != null) {
props.setProperty("password", password);
mergedProps.setProperty("password", password);
}
return getConnectionFromDriver(props);
return getConnectionFromDriver(mergedProps);
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -348,10 +348,6 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan
return this.newConnectionHolder;
}
public boolean hasTransaction() {
return (getConnectionHolder() != null && getConnectionHolder().isTransactionActive());
}
public void setMustRestoreAutoCommit(boolean mustRestoreAutoCommit) {
this.mustRestoreAutoCommit = mustRestoreAutoCommit;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -66,18 +66,17 @@ import org.springframework.core.Constants;
* You will get the same effect with non-transactional reads, but lazy fetching
* of JDBC Connections allows you to still perform reads in transactions.
*
* <p><b>NOTE:</b> This DataSource proxy needs to return wrapped Connections to
* handle lazy fetching of an actual JDBC Connection. Therefore, the returned
* Connections cannot be cast to a native JDBC Connection type like OracleConnection,
* or to a connection pool implementation type. Use a corresponding
* NativeJdbcExtractor to retrieve the native JDBC Connection.
* <p><b>NOTE:</b> This DataSource proxy needs to return wrapped Connections
* (which implement the {@link ConnectionProxy} interface) in order to handle
* lazy fetching of an actual JDBC Connection. Therefore, the returned Connections
* cannot be cast to a native JDBC Connection type such as OracleConnection or
* to a connection pool implementation type. Use a corresponding
* {@link org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor}
* or JDBC 4's {@link Connection#unwrap} to retrieve the native JDBC Connection.
*
* @author Juergen Hoeller
* @since 1.1.4
* @see ConnectionProxy
* @see DataSourceTransactionManager
* @see org.springframework.orm.hibernate3.HibernateTransactionManager
* @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor
*/
public class LazyConnectionDataSourceProxy extends DelegatingDataSource {
@@ -407,7 +406,13 @@ public class LazyConnectionDataSourceProxy extends DelegatingDataSource {
// Apply kept transaction settings, if any.
if (this.readOnly) {
this.target.setReadOnly(this.readOnly);
try {
this.target.setReadOnly(this.readOnly);
}
catch (Exception ex) {
// "read-only not supported" -> ignore, it's just a hint anyway
logger.debug("Could not set JDBC Connection read-only", ex);
}
}
if (this.transactionIsolation != null &&
!this.transactionIsolation.equals(defaultTransactionIsolation())) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -64,10 +64,10 @@ import org.springframework.util.Assert;
* <p><b>NOTE:</b> This DataSource proxy needs to return wrapped Connections
* (which implement the {@link ConnectionProxy} interface) in order to handle
* close calls properly. Therefore, the returned Connections cannot be cast
* to a native JDBC Connection type like OracleConnection or to a connection
* to a native JDBC Connection type such as OracleConnection or to a connection
* pool implementation type. Use a corresponding
* {@link org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor}
* to retrieve the native JDBC Connection.
* or JDBC 4's {@link Connection#unwrap} to retrieve the native JDBC Connection.
*
* @author Juergen Hoeller
* @since 1.1

View File

@@ -205,7 +205,6 @@ public class EmbeddedDatabaseFactory {
}
// getParentLogger() is required for JDBC 4.1 compatibility
@SuppressWarnings("unused")
public Logger getParentLogger() {
return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
}

View File

@@ -59,4 +59,4 @@ final class HsqlEmbeddedDatabaseConfigurer extends AbstractEmbeddedDatabaseConfi
properties.setPassword("");
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -20,7 +20,6 @@ import java.lang.reflect.Constructor;
import java.sql.BatchUpdateException;
import java.sql.SQLException;
import java.util.Arrays;
import javax.sql.DataSource;
import org.springframework.core.JdkVersion;
@@ -30,9 +29,9 @@ import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DeadlockLoserDataAccessException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.PermissionDeniedDataAccessException;
import org.springframework.dao.TransientDataAccessResourceException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.InvalidResultSetAccessException;
@@ -201,20 +200,25 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
// Check SQLErrorCodes with corresponding error code, if available.
if (this.sqlErrorCodes != null) {
String errorCode = null;
String errorCode;
if (this.sqlErrorCodes.isUseSqlStateForTranslation()) {
errorCode = sqlEx.getSQLState();
}
else {
errorCode = Integer.toString(sqlEx.getErrorCode());
// Try to find SQLException with actual error code, looping through the causes.
// E.g. applicable to java.sql.DataTruncation as of JDK 1.6.
SQLException current = sqlEx;
while (current.getErrorCode() == 0 && current.getCause() instanceof SQLException) {
current = (SQLException) current.getCause();
}
errorCode = Integer.toString(current.getErrorCode());
}
if (errorCode != null) {
// Look for defined custom translations first.
CustomSQLErrorCodesTranslation[] customTranslations = this.sqlErrorCodes.getCustomTranslations();
if (customTranslations != null) {
for (int i = 0; i < customTranslations.length; i++) {
CustomSQLErrorCodesTranslation customTranslation = customTranslations[i];
for (CustomSQLErrorCodesTranslation customTranslation : customTranslations) {
if (Arrays.binarySearch(customTranslation.getErrorCodes(), errorCode) >= 0) {
if (customTranslation.getExceptionClass() != null) {
DataAccessException customException = createCustomException(
@@ -273,7 +277,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
// We couldn't identify it more precisely - let's hand it over to the SQLState fallback translator.
if (logger.isDebugEnabled()) {
String codes = null;
String codes;
if (this.sqlErrorCodes != null && this.sqlErrorCodes.isUseSqlStateForTranslation()) {
codes = "SQL state '" + sqlEx.getSQLState() + "', error code '" + sqlEx.getErrorCode();
}
@@ -321,8 +325,8 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
try {
int constructorType = 0;
Constructor[] constructors = exceptionClass.getConstructors();
for (int i = 0; i < constructors.length; i++) {
Class[] parameterTypes = constructors[i].getParameterTypes();
for (Constructor constructor : constructors) {
Class[] parameterTypes = constructor.getParameterTypes();
if (parameterTypes.length == 1 && parameterTypes[0].equals(String.class)) {
if (constructorType < MESSAGE_ONLY_CONSTRUCTOR)
constructorType = MESSAGE_ONLY_CONSTRUCTOR;
@@ -350,7 +354,7 @@ public class SQLErrorCodeSQLExceptionTranslator extends AbstractFallbackSQLExcep
}
// invoke constructor
Constructor exceptionConstructor = null;
Constructor exceptionConstructor;
switch (constructorType) {
case MESSAGE_SQL_SQLEX_CONSTRUCTOR:
Class[] messageAndSqlAndSqlExArgsClass = new Class[] {String.class, String.class, SQLException.class};

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -22,7 +22,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Abstract base class for LobHandler implementations.
* Abstract base class for {@link LobHandler} implementations.
*
* <p>Implements all accessor methods for column names through a column lookup
* and delegating to the corresponding accessor that takes a column index.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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,18 +32,20 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Default implementation of the {@link LobHandler} interface. Invokes
* the direct accessor methods that {@code java.sql.ResultSet}
* Default implementation of the {@link LobHandler} interface.
* Invokes the direct accessor methods that {@code java.sql.ResultSet}
* and {@code java.sql.PreparedStatement} offer.
*
* <p>This LobHandler should work for any JDBC driver that is JDBC compliant
* in terms of the spec's suggestions regarding simple BLOB and CLOB handling.
* This does not apply to Oracle 9i, and only to a limited degree to Oracle 10g!
* As a consequence, use {@link OracleLobHandler} for accessing Oracle BLOBs/CLOBs.
* This does not apply to Oracle 9i's drivers at all; as of Oracle 10g,
* it does work but may still come with LOB size limitations. Consider using
* recent Oracle drivers even when working against an older database server.
* See the {@link LobHandler} javadoc for the full set of recommendations.
*
* <p>Some JDBC drivers require values with a BLOB/CLOB target column to be
* explicitly set through the JDBC {@code setBlob} / {@code setClob}
* API: for example, PostgreSQL's driver. Switch the {@link #setWrapAsLob "wrapAsLob"}
* explicitly set through the JDBC {@code setBlob} / {@code setClob} API:
* for example, PostgreSQL's driver. Switch the {@link #setWrapAsLob "wrapAsLob"}
* property to "true" when operating against such a driver.
*
* <p>On JDBC 4.0, this LobHandler also supports streaming the BLOB/CLOB content
@@ -51,11 +53,15 @@ import org.apache.commons.logging.LogFactory;
* argument directly. Consider switching the {@link #setStreamAsLob "streamAsLob"}
* property to "true" when operating against a fully compliant JDBC 4.0 driver.
*
* <p>See the {@link LobHandler} javadoc for a summary of recommendations.
* <p>Finally, primarily as a direct equivalent to {@link OracleLobHandler},
* this LobHandler also supports the creation of temporary BLOB/CLOB objects.
* Consider switching the {@link #setCreateTemporaryLob "createTemporaryLob"}
* property to "true" when "streamAsLob" happens to run into LOB size limitations.
*
* <p>See the {@link LobHandler} interface javadoc for a summary of recommendations.
*
* @author Juergen Hoeller
* @since 04.12.2003
* @see #setStreamAsLob
* @see java.sql.ResultSet#getBytes
* @see java.sql.ResultSet#getBinaryStream
* @see java.sql.ResultSet#getString
@@ -75,15 +81,18 @@ public class DefaultLobHandler extends AbstractLobHandler {
private boolean streamAsLob = false;
private boolean createTemporaryLob = false;
/**
* Specify whether to submit a byte array / String to the JDBC driver
* wrapped in a JDBC Blob / Clob object, using the JDBC {@code setBlob} /
* {@code setClob} method with a Blob / Clob argument.
* <p>Default is "false", using the common JDBC 2.0 {@code setBinaryStream}
* / {@code setCharacterStream} method for setting the content.
* Switch this to "true" for explicit Blob / Clob wrapping against
* JDBC drivers that are known to require such wrapping (e.g. PostgreSQL's).
* / {@code setCharacterStream} method for setting the content. Switch this
* to "true" for explicit Blob / Clob wrapping against JDBC drivers that
* are known to require such wrapping (e.g. PostgreSQL's for access to OID
* columns, whereas BYTEA columns need to be accessed the standard way).
* <p>This setting affects byte array / String arguments as well as stream
* arguments, unless {@link #setStreamAsLob "streamAsLob"} overrides this
* handling to use JDBC 4.0's new explicit streaming support (if available).
@@ -100,7 +109,7 @@ public class DefaultLobHandler extends AbstractLobHandler {
* {@code setClob} method with a stream argument.
* <p>Default is "false", using the common JDBC 2.0 {@code setBinaryStream}
* / {@code setCharacterStream} method for setting the content.
* Switch this to "true" for explicit JDBC 4.0 usage, provided that your
* Switch this to "true" for explicit JDBC 4.0 streaming, provided that your
* JDBC driver actually supports those JDBC 4.0 operations (e.g. Derby's).
* <p>This setting affects stream arguments as well as byte array / String
* arguments, requiring JDBC 4.0 support. For supporting LOB content against
@@ -112,6 +121,23 @@ public class DefaultLobHandler extends AbstractLobHandler {
this.streamAsLob = streamAsLob;
}
/**
* Specify whether to copy a byte array / String into a temporary JDBC
* Blob / Clob object created through the JDBC 4.0 {@code createBlob} /
* {@code createClob} methods.
* <p>Default is "false", using the common JDBC 2.0 {@code setBinaryStream}
* / {@code setCharacterStream} method for setting the content. Switch this
* to "true" for explicit Blob / Clob creation using JDBC 4.0.
* <p>This setting affects stream arguments as well as byte array / String
* arguments, requiring JDBC 4.0 support. For supporting LOB content against
* JDBC 3.0, check out the {@link #setWrapAsLob "wrapAsLob"} setting.
* @see java.sql.Connection#createBlob()
* @see java.sql.Connection#createClob()
*/
public void setCreateTemporaryLob(boolean createTemporaryLob) {
this.createTemporaryLob = createTemporaryLob;
}
public byte[] getBlobAsBytes(ResultSet rs, int columnIndex) throws SQLException {
logger.debug("Returning BLOB as bytes");
@@ -169,12 +195,12 @@ public class DefaultLobHandler extends AbstractLobHandler {
}
public LobCreator getLobCreator() {
return new DefaultLobCreator();
return (this.createTemporaryLob ? new TemporaryLobCreator() : new DefaultLobCreator());
}
/**
* Default LobCreator implementation as inner class.
* Default LobCreator implementation as an inner class.
* Can be subclassed in DefaultLobHandler extensions.
*/
protected class DefaultLobCreator implements LobCreator {
@@ -268,15 +294,10 @@ public class DefaultLobHandler extends AbstractLobHandler {
PreparedStatement ps, int paramIndex, InputStream asciiStream, int contentLength)
throws SQLException {
if (streamAsLob || wrapAsLob) {
if (streamAsLob) {
if (asciiStream != null) {
try {
if (streamAsLob) {
ps.setClob(paramIndex, new InputStreamReader(asciiStream, "US-ASCII"), contentLength);
}
else {
ps.setClob(paramIndex, new PassThroughClob(asciiStream, contentLength));
}
ps.setClob(paramIndex, new InputStreamReader(asciiStream, "US-ASCII"), contentLength);
}
catch (UnsupportedEncodingException ex) {
throw new SQLException("US-ASCII encoding not supported: " + ex);
@@ -286,6 +307,14 @@ public class DefaultLobHandler extends AbstractLobHandler {
ps.setClob(paramIndex, (Clob) null);
}
}
else if (wrapAsLob) {
if (asciiStream != null) {
ps.setClob(paramIndex, new PassThroughClob(asciiStream, contentLength));
}
else {
ps.setClob(paramIndex, (Clob) null);
}
}
else {
ps.setAsciiStream(paramIndex, asciiStream, contentLength);
}
@@ -325,7 +354,7 @@ public class DefaultLobHandler extends AbstractLobHandler {
}
public void close() {
// nothing to do here
// nothing to do when not creating temporary LOBs
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -24,7 +24,7 @@ import java.sql.SQLException;
/**
* Abstraction for handling large binary fields and large text fields in
* specific databases, no matter if represented as simple types or Large OBjects.
* Its main purpose is to isolate Oracle's peculiar handling of LOBs in
* Its main purpose is to isolate Oracle 9i's peculiar handling of LOBs in
* {@link OracleLobHandler}; most other databases should be able to work
* with the provided {@link DefaultLobHandler}.
*
@@ -45,8 +45,10 @@ import java.sql.SQLException;
* proprietary BLOB/CLOB API, and additionally doesn't accept large streams for
* PreparedStatement's corresponding setter methods. Therefore, you need to use
* {@link OracleLobHandler} there, which uses Oracle's BLOB/CLOB API for both types
* of access. The Oracle 10g JDBC driver should basically work with
* {@link DefaultLobHandler} as well, with some limitations in terms of LOB sizes.
* of access. The Oracle 10g+ JDBC driver will work with {@link DefaultLobHandler}
* as well, with some limitations in terms of LOB sizes depending on DBMS setup;
* as of Oracle 11g (or actually, using the 11g driver even against older databases),
* there should be no need to use {@link OracleLobHandler} at all anymore.
*
* <p>Of course, you need to declare different field types for each database.
* In Oracle, any binary content needs to go into a BLOB, and all character content
@@ -57,12 +59,20 @@ import java.sql.SQLException;
*
* <p><b>Summarizing the recommended options (for actual LOB fields):</b>
* <ul>
* <li><b>JDBC 4.0 driver:</b> {@link DefaultLobHandler} with {@code streamAsLob=true}.
* <li><b>PostgreSQL:</b> {@link DefaultLobHandler} with {@code wrapAsLob=true}.
* <li><b>Oracle 9i/10g:</b> {@link OracleLobHandler} with a connection-pool-specific
* <li><b>JDBC 4.0 driver (including Oracle 11g driver):</b> Use {@link DefaultLobHandler},
* potentially with {@code streamAsLob=true} if your database driver requires that
* hint when populating a LOB field. Fall back to {@code createTemporaryLob=true}
* if you happen to run into LOB size limitations with your (Oracle) database setup.
* <li><b>Oracle 10g driver:</b> Use {@link DefaultLobHandler} with standard setup.
* On Oracle 10.1, set the "SetBigStringTryClob" connection property; as of Oracle 10.2,
* DefaultLobHandler should work with standard setup out of the box. Alternatively,
* consider using the proprietary {@link OracleLobHandler} (see below).
* <li><b>Oracle 9i driver:</b> Use {@link OracleLobHandler} with a connection-pool-specific
* {@link OracleLobHandler#setNativeJdbcExtractor NativeJdbcExtractor}.
* <li><b>PostgreSQL:</b> Configure {@link DefaultLobHandler} with {@code wrapAsLob=true},
* and use that LobHandler to access OID columns (but not BYTEA) in your database tables.
* <li>For all other database drivers (and for non-LOB fields that might potentially
* turn into LOBs on some databases): a plain {@link DefaultLobHandler}.
* turn into LOBs on some databases): Simply use a plain {@link DefaultLobHandler}.
* </ul>
*
* @author Juergen Hoeller

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -49,14 +49,23 @@ import org.springframework.util.FileCopyUtils;
* Note that this LobHandler requires Oracle JDBC driver 9i or higher!
*
* <p>While most databases are able to work with {@link DefaultLobHandler},
* Oracle just accepts Blob/Clob instances created via its own proprietary
* BLOB/CLOB API, and additionally doesn't accept large streams for
* PreparedStatement's corresponding setter methods. Therefore, you need
* to use a strategy like this LobHandler implementation.
* Oracle 9i (or more specifically, the Oracle 9i JDBC driver) just accepts
* Blob/Clob instances created via its own proprietary BLOB/CLOB API,
* and additionally doesn't accept large streams for PreparedStatement's
* corresponding setter methods. Therefore, you need to use a strategy like
* this LobHandler implementation, or upgrade to the Oracle 10g/11g driver
* (which still supports access to Oracle 9i databases).
*
* <p><b>NOTE: As of Oracle 10.2, {@link DefaultLobHandler} should work equally
* well out of the box. On Oracle 11g, JDBC 4.0 based options such as
* {@link DefaultLobHandler#setStreamAsLob} and {@link DefaultLobHandler#setCreateTemporaryLob}
* are available as well, rendering this proprietary OracleLobHandler obsolete.</b>
* Also, consider upgrading to a new driver even when accessing an older database.
* See the {@link LobHandler} interface javadoc for a summary of recommendations.
*
* <p>Needs to work on a native JDBC Connection, to be able to cast it to
* {@code oracle.jdbc.OracleConnection}. If you pass in Connections from a
* connection pool (the usual case in a J2EE environment), you need to set an
* connection pool (the usual case in a Java EE environment), you need to set an
* appropriate {@link org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor}
* to allow for automatic retrieval of the underlying native JDBC Connection.
* LobHandler and NativeJdbcExtractor are separate concerns, therefore they
@@ -72,8 +81,15 @@ import org.springframework.util.FileCopyUtils;
* @author Juergen Hoeller
* @author Thomas Risberg
* @since 04.12.2003
* @see DefaultLobHandler
* @see #setNativeJdbcExtractor
* @deprecated in favor of {@link DefaultLobHandler} for the Oracle 10g driver and
* higher. Consider using the 10g/11g driver even against an Oracle 9i database!
* {@link DefaultLobHandler#setCreateTemporaryLob} is the direct equivalent of this
* OracleLobHandler's implementation strategy, just using standard JDBC 4.0 API.
* That said, in most cases, regular DefaultLobHandler setup will work fine as well.
*/
@Deprecated
public class OracleLobHandler extends AbstractLobHandler {
private static final String BLOB_CLASS_NAME = "oracle.sql.BLOB";
@@ -143,7 +159,7 @@ public class OracleLobHandler extends AbstractLobHandler {
}
/**
* Set whether to agressively release any resources used by the LOB. If set to {@code true}
* Set whether to aggressively release any resources used by the LOB. If set to {@code true}
* then you can only read the LOB values once. Any subsequent reads will fail since the resources
* have been closed.
* <p>Setting this property to {@code true} can be useful when your queries generates large
@@ -283,7 +299,7 @@ public class OracleLobHandler extends AbstractLobHandler {
((BLOB) lob).open(BLOB.MODE_READONLY);
*/
Method open = lob.getClass().getMethod("open", int.class);
open.invoke(lob, modeReadOnlyConstants.get(lob.getClass()));
open.invoke(lob, this.modeReadOnlyConstants.get(lob.getClass()));
}
}
catch (InvocationTargetException ex) {
@@ -366,7 +382,7 @@ public class OracleLobHandler extends AbstractLobHandler {
*/
protected class OracleLobCreator implements LobCreator {
private final List createdLobs = new LinkedList();
private final List<Object> temporaryLobs = new LinkedList<Object>();
public void setBlobAsBytes(PreparedStatement ps, int paramIndex, final byte[] content)
throws SQLException {
@@ -495,7 +511,7 @@ public class OracleLobHandler extends AbstractLobHandler {
Object lob = prepareLob(con, clob ? clobClass : blobClass);
callback.populateLob(lob);
lob.getClass().getMethod("close", (Class[]) null).invoke(lob, (Object[]) null);
this.createdLobs.add(lob);
this.temporaryLobs.add(lob);
if (logger.isDebugEnabled()) {
logger.debug("Created new Oracle " + (clob ? "CLOB" : "BLOB"));
}
@@ -556,7 +572,7 @@ public class OracleLobHandler extends AbstractLobHandler {
*/
public void close() {
try {
for (Iterator it = this.createdLobs.iterator(); it.hasNext();) {
for (Iterator it = this.temporaryLobs.iterator(); it.hasNext();) {
/*
BLOB blob = (BLOB) it.next();
blob.freeTemporary();

View File

@@ -0,0 +1,167 @@
/*
* Copyright 2002-2013 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.jdbc.support.lob;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.util.FileCopyUtils;
/**
* {@link LobCreator} implementation based on temporary LOBs,
* using JDBC 4.0's {@link java.sql.Connection#createBlob()} /
* {@link java.sql.Connection#createClob()} mechanism.
*
* <p>Used by DefaultLobHandler's {@link DefaultLobHandler#setCreateTemporaryLob} mode.
* Can also be used directly to reuse the tracking and freeing of temporary LOBs.
*
* @author Juergen Hoeller
* @since 3.2.2
* @see DefaultLobHandler#setCreateTemporaryLob
* @see java.sql.Connection#createBlob()
* @see java.sql.Connection#createClob()
*/
public class TemporaryLobCreator implements LobCreator {
protected static final Log logger = LogFactory.getLog(TemporaryLobCreator.class);
private final Set<Blob> temporaryBlobs = new LinkedHashSet<Blob>(1);
private final Set<Clob> temporaryClobs = new LinkedHashSet<Clob>(1);
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 (logger.isDebugEnabled()) {
logger.debug(content != null ? "Copied bytes into temporary BLOB with length " + content.length :
"Set BLOB to null");
}
}
public void setBlobAsBinaryStream(
PreparedStatement ps, int paramIndex, InputStream binaryStream, int contentLength)
throws SQLException {
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);
if (logger.isDebugEnabled()) {
logger.debug(binaryStream != null ?
"Copied binary stream into temporary BLOB with length " + contentLength :
"Set BLOB to null");
}
}
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 (logger.isDebugEnabled()) {
logger.debug(content != null ? "Copied string into temporary CLOB with length " + content.length() :
"Set CLOB to null");
}
}
public void setClobAsAsciiStream(
PreparedStatement ps, int paramIndex, InputStream asciiStream, int contentLength)
throws SQLException {
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);
if (logger.isDebugEnabled()) {
logger.debug(asciiStream != null ?
"Copied ASCII stream into temporary CLOB with length " + contentLength :
"Set CLOB to null");
}
}
public void setClobAsCharacterStream(
PreparedStatement ps, int paramIndex, Reader characterStream, int contentLength)
throws SQLException {
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);
if (logger.isDebugEnabled()) {
logger.debug(characterStream != null ?
"Copied character stream into temporary CLOB with length " + contentLength :
"Set CLOB to null");
}
}
public void close() {
try {
for (Blob blob : this.temporaryBlobs) {
blob.free();
}
for (Clob clob : this.temporaryClobs) {
clob.free();
}
}
catch (SQLException ex) {
logger.error("Could not free LOB", ex);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -24,7 +24,7 @@ import org.springframework.util.ReflectionUtils;
/**
* Implementation of the {@link NativeJdbcExtractor} interface for WebLogic,
* supporting WebLogic Server 8.1 and higher.
* supporting WebLogic Server 9.0 and higher.
*
* <p>Returns the underlying native Connection to application code instead
* of WebLogic's wrapper implementation; unwraps the Connection for native

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@@ -24,7 +24,7 @@ import org.springframework.util.ReflectionUtils;
/**
* Implementation of the {@link NativeJdbcExtractor} interface for WebSphere,
* supporting WebSphere Application Server 5.1 and higher.
* supporting WebSphere Application Server 6.1 and higher.
*
* <p>Returns the underlying native Connection to application code instead
* of WebSphere's wrapper implementation; unwraps the Connection for
@@ -40,14 +40,14 @@ import org.springframework.util.ReflectionUtils;
*/
public class WebSphereNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
private static final String JDBC_ADAPTER_CONNECTION_NAME_5 = "com.ibm.ws.rsadapter.jdbc.WSJdbcConnection";
private static final String JDBC_ADAPTER_CONNECTION_NAME = "com.ibm.ws.rsadapter.jdbc.WSJdbcConnection";
private static final String JDBC_ADAPTER_UTIL_NAME_5 = "com.ibm.ws.rsadapter.jdbc.WSJdbcUtil";
private static final String JDBC_ADAPTER_UTIL_NAME = "com.ibm.ws.rsadapter.jdbc.WSJdbcUtil";
private Class webSphere5ConnectionClass;
private Class webSphereConnectionClass;
private Method webSphere5NativeConnectionMethod;
private Method webSphereNativeConnectionMethod;
/**
@@ -56,10 +56,10 @@ public class WebSphereNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
*/
public WebSphereNativeJdbcExtractor() {
try {
this.webSphere5ConnectionClass = getClass().getClassLoader().loadClass(JDBC_ADAPTER_CONNECTION_NAME_5);
Class jdbcAdapterUtilClass = getClass().getClassLoader().loadClass(JDBC_ADAPTER_UTIL_NAME_5);
this.webSphere5NativeConnectionMethod =
jdbcAdapterUtilClass.getMethod("getNativeConnection", new Class[] {this.webSphere5ConnectionClass});
this.webSphereConnectionClass = getClass().getClassLoader().loadClass(JDBC_ADAPTER_CONNECTION_NAME);
Class jdbcAdapterUtilClass = getClass().getClassLoader().loadClass(JDBC_ADAPTER_UTIL_NAME);
this.webSphereNativeConnectionMethod =
jdbcAdapterUtilClass.getMethod("getNativeConnection", new Class[] {this.webSphereConnectionClass});
}
catch (Exception ex) {
throw new IllegalStateException(
@@ -97,9 +97,8 @@ public class WebSphereNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
*/
@Override
protected Connection doGetNativeConnection(Connection con) throws SQLException {
if (this.webSphere5ConnectionClass.isAssignableFrom(con.getClass())) {
return (Connection) ReflectionUtils.invokeJdbcMethod(
this.webSphere5NativeConnectionMethod, null, new Object[] {con});
if (this.webSphereConnectionClass.isAssignableFrom(con.getClass())) {
return (Connection) ReflectionUtils.invokeJdbcMethod(this.webSphereNativeConnectionMethod, null, con);
}
return con;
}