Drop NativeJdbcExtractor mechanism in favor of JDBC 4 unwrap

Issue: SPR-14670
This commit is contained in:
Juergen Hoeller 2017-02-15 18:04:08 +01:00
parent 54f01cffaf
commit 07dd61eabd
36 changed files with 124 additions and 1693 deletions

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.
@ -26,7 +26,6 @@ import java.util.List;
import java.util.Map;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
/**
* Helper class that efficiently creates multiple {@link CallableStatementCreator}
@ -49,8 +48,6 @@ public class CallableStatementCreatorFactory {
private boolean updatableResults = false;
private NativeJdbcExtractor nativeJdbcExtractor;
/**
* Create a new factory. Will need to add parameters via the
@ -100,13 +97,6 @@ public class CallableStatementCreatorFactory {
this.updatableResults = updatableResults;
}
/**
* Specify the NativeJdbcExtractor to use for unwrapping CallableStatements, if any.
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.nativeJdbcExtractor = nativeJdbcExtractor;
}
/**
* Return a new CallableStatementCreator instance given this parameters.
@ -172,12 +162,6 @@ public class CallableStatementCreatorFactory {
updatableResults ? ResultSet.CONCUR_UPDATABLE : ResultSet.CONCUR_READ_ONLY);
}
// Determine CallabeStatement to pass to custom types.
CallableStatement csToUse = cs;
if (nativeJdbcExtractor != null) {
csToUse = nativeJdbcExtractor.getNativeCallableStatement(cs);
}
int sqlColIndx = 1;
for (SqlParameter declaredParam : declaredParameters) {
if (!declaredParam.isResultsParameter()) {
@ -200,7 +184,7 @@ public class CallableStatementCreatorFactory {
}
}
if (declaredParam.isInputValueProvided()) {
StatementCreatorUtils.setParameterValue(csToUse, sqlColIndx, declaredParam, inValue);
StatementCreatorUtils.setParameterValue(cs, sqlColIndx, declaredParam, inValue);
}
}
}
@ -210,7 +194,7 @@ public class CallableStatementCreatorFactory {
throw new InvalidDataAccessApiUsageException(
"Required input parameter '" + declaredParam.getName() + "' is missing");
}
StatementCreatorUtils.setParameterValue(csToUse, sqlColIndx, declaredParam, inValue);
StatementCreatorUtils.setParameterValue(cs, sqlColIndx, declaredParam, inValue);
}
sqlColIndx++;
}
@ -233,10 +217,7 @@ public class CallableStatementCreatorFactory {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("CallableStatementCreatorFactory.CallableStatementCreatorImpl: sql=[");
sb.append(callString).append("]; parameters=").append(this.inParameters);
return sb.toString();
return "CallableStatementCreator: sql=[" + callString + "]; parameters=" + this.inParameters;
}
}

View File

@ -46,7 +46,6 @@ import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.jdbc.support.JdbcAccessor;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.util.Assert;
import org.springframework.util.LinkedCaseInsensitiveMap;
@ -104,9 +103,6 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
private static final String RETURN_UPDATE_COUNT_PREFIX = "#update-count-";
/** Custom NativeJdbcExtractor */
private NativeJdbcExtractor nativeJdbcExtractor;
/** If this variable is false, we will throw exceptions on SQL warnings */
private boolean ignoreWarnings = true;
@ -182,23 +178,6 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
}
/**
* Set a NativeJdbcExtractor to extract native JDBC objects from wrapped handles.
* Useful if native Statement and/or ResultSet handles are expected for casting
* to database-specific implementation classes, but a connection pool that wraps
* JDBC objects is used (note: <i>any</i> pool will return wrapped Connections).
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor extractor) {
this.nativeJdbcExtractor = extractor;
}
/**
* Return the current NativeJdbcExtractor implementation.
*/
public NativeJdbcExtractor getNativeJdbcExtractor() {
return this.nativeJdbcExtractor;
}
/**
* Set whether or not we want to ignore SQLWarnings.
* <p>Default is "true", swallowing and logging all warnings. Switch this flag
@ -341,15 +320,8 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
Connection con = DataSourceUtils.getConnection(getDataSource());
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null) {
// Extract native JDBC Connection, castable to OracleConnection or the like.
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
else {
// Create close-suppressing Connection proxy, also preparing returned Statements.
conToUse = createConnectionProxy(con);
}
// Create close-suppressing Connection proxy, also preparing returned Statements.
Connection conToUse = createConnectionProxy(con);
return action.doInConnection(conToUse);
}
catch (SQLException ex) {
@ -394,18 +366,9 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
Connection con = DataSourceUtils.getConnection(getDataSource());
Statement stmt = null;
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null &&
this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
stmt = conToUse.createStatement();
stmt = con.createStatement();
applyStatementSettings(stmt);
Statement stmtToUse = stmt;
if (this.nativeJdbcExtractor != null) {
stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
}
T result = action.doInStatement(stmtToUse);
T result = action.doInStatement(stmt);
handleWarnings(stmt);
return result;
}
@ -456,11 +419,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
ResultSet rs = null;
try {
rs = stmt.executeQuery(sql);
ResultSet rsToUse = rs;
if (nativeJdbcExtractor != null) {
rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);
}
return rse.extractData(rsToUse);
return rse.extractData(rs);
}
finally {
JdbcUtils.closeResultSet(rs);
@ -619,18 +578,9 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
Connection con = DataSourceUtils.getConnection(getDataSource());
PreparedStatement ps = null;
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null &&
this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
ps = psc.createPreparedStatement(conToUse);
ps = psc.createPreparedStatement(con);
applyStatementSettings(ps);
PreparedStatement psToUse = ps;
if (this.nativeJdbcExtractor != null) {
psToUse = this.nativeJdbcExtractor.getNativePreparedStatement(ps);
}
T result = action.doInPreparedStatement(psToUse);
T result = action.doInPreparedStatement(ps);
handleWarnings(ps);
return result;
}
@ -690,11 +640,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
pss.setValues(ps);
}
rs = ps.executeQuery();
ResultSet rsToUse = rs;
if (nativeJdbcExtractor != null) {
rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);
}
return rse.extractData(rsToUse);
return rse.extractData(rs);
}
finally {
JdbcUtils.closeResultSet(rs);
@ -1070,17 +1016,9 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
Connection con = DataSourceUtils.getConnection(getDataSource());
CallableStatement cs = null;
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
cs = csc.createCallableStatement(conToUse);
cs = csc.createCallableStatement(con);
applyStatementSettings(cs);
CallableStatement csToUse = cs;
if (this.nativeJdbcExtractor != null) {
csToUse = this.nativeJdbcExtractor.getNativeCallableStatement(cs);
}
T result = action.doInCallableStatement(csToUse);
T result = action.doInCallableStatement(cs);
handleWarnings(cs);
return result;
}
@ -1274,22 +1212,18 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
}
Map<String, Object> returnedResults = new HashMap<>();
try {
ResultSet rsToUse = rs;
if (this.nativeJdbcExtractor != null) {
rsToUse = this.nativeJdbcExtractor.getNativeResultSet(rs);
}
if (param.getRowMapper() != null) {
RowMapper rowMapper = param.getRowMapper();
Object result = (new RowMapperResultSetExtractor(rowMapper)).extractData(rsToUse);
Object result = (new RowMapperResultSetExtractor(rowMapper)).extractData(rs);
returnedResults.put(param.getName(), result);
}
else if (param.getRowCallbackHandler() != null) {
RowCallbackHandler rch = param.getRowCallbackHandler();
(new RowCallbackHandlerResultSetExtractor(rch)).extractData(rsToUse);
(new RowCallbackHandlerResultSetExtractor(rch)).extractData(rs);
returnedResults.put(param.getName(), "ResultSet returned from stored procedure was processed");
}
else if (param.getResultSetExtractor() != null) {
Object result = param.getResultSetExtractor().extractData(rsToUse);
Object result = param.getResultSetExtractor().extractData(rs);
returnedResults.put(param.getName(), result);
}
}

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.
@ -30,7 +30,6 @@ import java.util.List;
import java.util.Set;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.util.Assert;
/**
@ -58,8 +57,6 @@ public class PreparedStatementCreatorFactory {
private String[] generatedKeysColumnNames = null;
private NativeJdbcExtractor nativeJdbcExtractor;
/**
* Create a new factory. Will need to add parameters via the
@ -133,13 +130,6 @@ public class PreparedStatementCreatorFactory {
this.generatedKeysColumnNames = names;
}
/**
* Specify the NativeJdbcExtractor to use for unwrapping PreparedStatements, if any.
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.nativeJdbcExtractor = nativeJdbcExtractor;
}
/**
* Return a new PreparedStatementSetter for the given parameters.
@ -247,12 +237,6 @@ public class PreparedStatementCreatorFactory {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
// Determine PreparedStatement to pass to custom types.
PreparedStatement psToUse = ps;
if (nativeJdbcExtractor != null) {
psToUse = nativeJdbcExtractor.getNativePreparedStatement(ps);
}
// Set arguments: Does nothing if there are no parameters.
int sqlColIndx = 1;
for (int i = 0; i < this.parameters.size(); i++) {
@ -280,16 +264,16 @@ public class PreparedStatementCreatorFactory {
if (entry instanceof Object[]) {
Object[] valueArray = ((Object[])entry);
for (Object argValue : valueArray) {
StatementCreatorUtils.setParameterValue(psToUse, sqlColIndx++, declaredParameter, argValue);
StatementCreatorUtils.setParameterValue(ps, sqlColIndx++, declaredParameter, argValue);
}
}
else {
StatementCreatorUtils.setParameterValue(psToUse, sqlColIndx++, declaredParameter, entry);
StatementCreatorUtils.setParameterValue(ps, sqlColIndx++, declaredParameter, entry);
}
}
}
else {
StatementCreatorUtils.setParameterValue(psToUse, sqlColIndx++, declaredParameter, in);
StatementCreatorUtils.setParameterValue(ps, sqlColIndx++, declaredParameter, in);
}
}
}
@ -306,10 +290,7 @@ public class PreparedStatementCreatorFactory {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("PreparedStatementCreatorFactory.PreparedStatementCreatorImpl: sql=[");
sb.append(sql).append("]; parameters=").append(this.parameters);
return sb.toString();
return "PreparedStatementCreator: sql=[" + sql + "]; parameters=" + this.parameters;
}
}

View File

@ -45,8 +45,8 @@ public interface CallMetaDataProvider {
* This is only called for databases that are supported. This initialization
* can be turned off by specifying that column meta data should not be used.
* @param databaseMetaData used to retrieve database specific information
* @param catalogName name of catalog to use or null
* @param schemaName name of schema name to use or null
* @param catalogName name of catalog to use (or {@code null} if none)
* @param schemaName name of schema name to use (or {@code null} if none)
* @param procedureName name of the stored procedure
* @throws SQLException in case of initialization failure
* @see org.springframework.jdbc.core.simple.SimpleJdbcCall#withoutProcedureColumnMetaDataAccess()

View File

@ -31,7 +31,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
/**
* A generic implementation of the {@link TableMetaDataProvider} that should provide
@ -74,13 +73,10 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
/** Collection of TableParameterMetaData objects */
private List<TableParameterMetaData> tableParameterMetaData = new ArrayList<>();
/** NativeJdbcExtractor that can be used to retrieve the native connection */
private NativeJdbcExtractor nativeJdbcExtractor;
/**
* Constructor used to initialize with provided database meta data.
* @param databaseMetaData meta data to be used
* Constructor used to initialize with provided database metadata.
* @param databaseMetaData metadata to be used
*/
protected GenericTableMetaDataProvider(DatabaseMetaData databaseMetaData) throws SQLException {
this.userName = databaseMetaData.getUserName();
@ -142,15 +138,6 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
return this.generatedKeysColumnNameArraySupported;
}
@Override
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.nativeJdbcExtractor = nativeJdbcExtractor;
}
protected NativeJdbcExtractor getNativeJdbcExtractor() {
return this.nativeJdbcExtractor;
}
@Override
public void initializeWithMetaData(DatabaseMetaData databaseMetaData) throws SQLException {
@ -308,7 +295,7 @@ public class GenericTableMetaDataProvider implements TableMetaDataProvider {
}
/**
* Method supporting the metedata processing for a table.
* Method supporting the metadata processing for a table.
*/
private void locateTableAndProcessMetaData(
DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String tableName) {

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.
@ -24,13 +24,12 @@ import java.sql.SQLException;
import java.sql.Types;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.util.ReflectionUtils;
/**
* Oracle-specific implementation of the {@link org.springframework.jdbc.core.metadata.TableMetaDataProvider}.
* Supports a feature for including synonyms in the metadata lookup. Also supports lookup of current schema
* using the sys_context.
* using the {@code sys_context}.
*
* <p>Thanks to Mike Youngstrom and Bruce Campbell for submitting the original suggestion for the Oracle
* current schema lookup implementation.
@ -46,17 +45,53 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
private String defaultSchema;
/**
* Constructor used to initialize with provided database metadata.
* @param databaseMetaData metadata to be used
*/
public OracleTableMetaDataProvider(DatabaseMetaData databaseMetaData) throws SQLException {
this(databaseMetaData, false);
}
public OracleTableMetaDataProvider(DatabaseMetaData databaseMetaData, boolean includeSynonyms) throws SQLException {
/**
* Constructor used to initialize with provided database metadata.
* @param databaseMetaData metadata to be used
* @param includeSynonyms whether to include synonyms
*/
public OracleTableMetaDataProvider(DatabaseMetaData databaseMetaData, boolean includeSynonyms)
throws SQLException {
super(databaseMetaData);
this.includeSynonyms = includeSynonyms;
lookupDefaultSchema(databaseMetaData);
}
/*
* Oracle-based implementation for detecting the current schema.
*/
private void lookupDefaultSchema(DatabaseMetaData databaseMetaData) {
try {
CallableStatement cstmt = null;
try {
cstmt = databaseMetaData.getConnection().prepareCall(
"{? = call sys_context('USERENV', 'CURRENT_SCHEMA')}");
cstmt.registerOutParameter(1, Types.VARCHAR);
cstmt.execute();
this.defaultSchema = cstmt.getString(1);
}
finally {
if (cstmt != null) {
cstmt.close();
}
}
}
catch (SQLException ex) {
logger.debug("Encountered exception during default schema lookup", ex);
}
}
@Override
protected String getDefaultSchema() {
if (this.defaultSchema != null) {
@ -65,6 +100,7 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
return super.getDefaultSchema();
}
@Override
public void initializeWithTableColumnMetaData(DatabaseMetaData databaseMetaData,
String catalogName, String schemaName, String tableName) throws SQLException {
@ -76,25 +112,12 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
}
Connection con = databaseMetaData.getConnection();
NativeJdbcExtractor nativeJdbcExtractor = getNativeJdbcExtractor();
if (nativeJdbcExtractor != null) {
con = nativeJdbcExtractor.getNativeConnection(con);
}
boolean isOracleCon;
try {
Class<?> oracleConClass = con.getClass().getClassLoader().loadClass("oracle.jdbc.OracleConnection");
isOracleCon = oracleConClass.isInstance(con);
con = (Connection) con.unwrap(oracleConClass);
}
catch (ClassNotFoundException ex) {
if (logger.isInfoEnabled()) {
logger.info("Couldn't find Oracle JDBC API: " + ex);
}
isOracleCon = false;
}
if (!isOracleCon) {
logger.warn("Unable to include synonyms in table metadata lookup. Connection used for " +
"DatabaseMetaData is not recognized as an Oracle connection: " + con);
catch (ClassNotFoundException | SQLException ex) {
logger.warn("Unable to include synonyms in table metadata lookup - no Oracle Connection: " + ex);
super.initializeWithTableColumnMetaData(databaseMetaData, catalogName, schemaName, tableName);
return;
}
@ -112,8 +135,8 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
ReflectionUtils.makeAccessible(setIncludeSynonyms);
setIncludeSynonyms.invoke(con, Boolean.TRUE);
}
catch (Exception ex) {
throw new InvalidDataAccessApiUsageException("Couldn't prepare Oracle Connection", ex);
catch (Throwable ex) {
throw new InvalidDataAccessApiUsageException("Could not prepare Oracle Connection", ex);
}
super.initializeWithTableColumnMetaData(databaseMetaData, catalogName, schemaName, tableName);
@ -121,30 +144,8 @@ public class OracleTableMetaDataProvider extends GenericTableMetaDataProvider {
try {
setIncludeSynonyms.invoke(con, originalValueForIncludeSynonyms);
}
catch (Exception ex) {
throw new InvalidDataAccessApiUsageException("Couldn't reset Oracle Connection", ex);
}
}
/*
* Oracle-based implementation for detecting the current schema.
*/
private void lookupDefaultSchema(DatabaseMetaData databaseMetaData) {
try {
CallableStatement cstmt = null;
try {
cstmt = databaseMetaData.getConnection().prepareCall("{? = call sys_context('USERENV', 'CURRENT_SCHEMA')}");
cstmt.registerOutParameter(1, Types.VARCHAR);
cstmt.execute();
this.defaultSchema = cstmt.getString(1);
}
finally {
if (cstmt != null) {
cstmt.close();
}
}
}
catch (Exception ignore) {
catch (Throwable ex) {
throw new InvalidDataAccessApiUsageException("Could not reset Oracle Connection", ex);
}
}

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.
@ -32,7 +32,6 @@ import org.springframework.jdbc.core.SqlTypeValue;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
/**
* Class to manage context metadata used for the configuration
@ -71,9 +70,6 @@ public class TableMetaDataContext {
/** are we using generated key columns */
private boolean generatedKeyColumnsUsed = false;
/** NativeJdbcExtractor to be used to retrieve the native connection */
NativeJdbcExtractor nativeJdbcExtractor;
/**
* Set the name of the table for this context.
@ -187,13 +183,6 @@ public class TableMetaDataContext {
return this.metaDataProvider.isGeneratedKeysColumnNameArraySupported();
}
/**
* Set {@link NativeJdbcExtractor} to be used to retrieve the native connection.
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.nativeJdbcExtractor = nativeJdbcExtractor;
}
/**
* Process the current meta data with the provided configuration options.
@ -202,8 +191,7 @@ public class TableMetaDataContext {
* @param generatedKeyNames name of generated keys
*/
public void processMetaData(DataSource dataSource, List<String> declaredColumns, String[] generatedKeyNames) {
this.metaDataProvider =
TableMetaDataProviderFactory.createMetaDataProvider(dataSource, this, this.nativeJdbcExtractor);
this.metaDataProvider = TableMetaDataProviderFactory.createMetaDataProvider(dataSource, this);
this.tableColumns = reconcileColumnsToUse(declaredColumns, generatedKeyNames);
}

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.
@ -20,11 +20,9 @@ import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
/**
* Interface specifying the API to be implemented by a class providing table metedata. This is intended for internal use
* by the Simple JDBC classes.
* Interface specifying the API to be implemented by a class providing table metadata.
* This is intended for internal use by the Simple JDBC classes.
*
* @author Thomas Risberg
* @since 2.5
@ -32,45 +30,37 @@ import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
public interface TableMetaDataProvider {
/**
* Initialize using the database metedata provided
* @param databaseMetaData
* @throws SQLException
* Initialize using the database metadata provided.
* @param databaseMetaData used to retrieve database specific information
* @throws SQLException in case of initialization failure
*/
void initializeWithMetaData(DatabaseMetaData databaseMetaData) throws SQLException;
/**
* Initialize using provided database metadata, table and column information. This initalization can be
* turned off by specifying that column meta data should not be used.
* Initialize using provided database metadata, table and column information.
* This initialization can be turned off by specifying that column meta data should not be used.
* @param databaseMetaData used to retrieve database specific information
* @param catalogName name of catalog to use or null
* @param schemaName name of schema name to use or null
* @param catalogName name of catalog to use (or {@code null} if none)
* @param schemaName name of schema name to use (or {@code null} if none)
* @param tableName name of the table
* @throws SQLException
* @throws SQLException in case of initialization failure
*/
void initializeWithTableColumnMetaData(DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String tableName)
void initializeWithTableColumnMetaData(
DatabaseMetaData databaseMetaData, String catalogName, String schemaName, String tableName)
throws SQLException;
/**
* Get the table name formatted based on metadata information. This could include altering the case.
*
* @param tableName
* @return table name formatted
*/
String tableNameToUse(String tableName);
/**
* Get the catalog name formatted based on metadata information. This could include altering the case.
*
* @param catalogName
* @return catalog name formatted
*/
String catalogNameToUse(String catalogName);
/**
* Get the schema name formatted based on metadata information. This could include altering the case.
*
* @param schemaName
* @return schema name formatted
*/
String schemaNameToUse(String schemaName);
@ -78,9 +68,6 @@ public interface TableMetaDataProvider {
* Provide any modification of the catalog name passed in to match the meta data currently used.
* 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
*/
String metaDataCatalogNameToUse(String catalogName) ;
@ -88,9 +75,6 @@ public interface TableMetaDataProvider {
* Provide any modification of the schema name passed in to match the meta data currently used.
* 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
*/
String metaDataSchemaNameToUse(String schemaName) ;
@ -100,15 +84,15 @@ public interface TableMetaDataProvider {
boolean isTableColumnMetaDataUsed();
/**
* Does this database support the JDBC 3.0 feature of retreiving generated keys
* {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}
* Does this database support the JDBC 3.0 feature of retrieving generated keys
* {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}?
*/
boolean isGetGeneratedKeysSupported();
/**
* Does this database support a simple quey to retrieve the generated key whe the JDBC 3.0 feature
* of retreiving generated keys is not supported
* {@link java.sql.DatabaseMetaData#supportsGetGeneratedKeys()}
* Does this database support a simple query to retrieve the generated key when
* the JDBC 3.0 feature of retrieving generated keys is not supported?
* @see #isGetGeneratedKeysSupported()
*/
boolean isGetGeneratedKeysSimulated();
@ -118,7 +102,7 @@ public interface TableMetaDataProvider {
String getSimpleQueryForGetGeneratedKey(String tableName, String keyColumnName);
/**
* Does this database support a column name String array for retreiving generated keys
* Does this database support a column name String array for retrieving generated keys
* {@link java.sql.Connection#createStruct(String, Object[])}
*/
boolean isGeneratedKeysColumnNameArraySupported();
@ -129,8 +113,4 @@ public interface TableMetaDataProvider {
*/
List<TableParameterMetaData> getTableParameterMetaData();
/**
* Set the {@link NativeJdbcExtractor} to use to retrieve the native connection if necessary
*/
void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor);
}

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.
@ -27,7 +27,6 @@ import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.support.DatabaseMetaDataCallback;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.MetaDataAccessException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
/**
* Factory used to create a {@link TableMetaDataProvider} implementation
@ -42,24 +41,12 @@ public class TableMetaDataProviderFactory {
/**
* Create a TableMetaDataProvider based on the database metedata
* @param dataSource used to retrieve metedata
* @param context the class that holds configuration and metedata
* Create a TableMetaDataProvider based on the database metadata.
* @param dataSource used to retrieve metadata
* @param context the class that holds configuration and metadata
* @return instance of the TableMetaDataProvider implementation to be used
*/
public static TableMetaDataProvider createMetaDataProvider(DataSource dataSource, TableMetaDataContext context) {
return createMetaDataProvider(dataSource, context, null);
}
/**
* Create a TableMetaDataProvider based on the database metedata
* @param dataSource used to retrieve metedata
* @param context the class that holds configuration and metedata
* @param nativeJdbcExtractor the NativeJdbcExtractor to be used
* @return instance of the TableMetaDataProvider implementation to be used
*/
public static TableMetaDataProvider createMetaDataProvider(DataSource dataSource,
final TableMetaDataContext context, final NativeJdbcExtractor nativeJdbcExtractor) {
try {
return (TableMetaDataProvider) JdbcUtils.extractDatabaseMetaData(dataSource,
new DatabaseMetaDataCallback() {
@ -85,9 +72,6 @@ public class TableMetaDataProviderFactory {
else {
provider = new GenericTableMetaDataProvider(databaseMetaData);
}
if (nativeJdbcExtractor != null) {
provider.setNativeJdbcExtractor(nativeJdbcExtractor);
}
if (logger.isDebugEnabled()) {
logger.debug("Using " + provider.getClass().getSimpleName());
}

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.
@ -317,7 +317,6 @@ public abstract class AbstractJdbcCall {
this.callableStatementFactory =
new CallableStatementCreatorFactory(getCallString(), this.callMetaDataContext.getCallParameters());
this.callableStatementFactory.setNativeJdbcExtractor(getJdbcTemplate().getNativeJdbcExtractor());
onCompileInternal();
}

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.
@ -47,7 +47,6 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.util.Assert;
/**
@ -104,7 +103,6 @@ public abstract class AbstractJdbcInsert {
protected AbstractJdbcInsert(JdbcTemplate jdbcTemplate) {
Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null");
this.jdbcTemplate = jdbcTemplate;
setNativeJdbcExtractor(jdbcTemplate.getNativeJdbcExtractor());
}
@ -219,13 +217,6 @@ public abstract class AbstractJdbcInsert {
this.tableMetaDataContext.setOverrideIncludeSynonymsDefault(override);
}
/**
* Set the {@link NativeJdbcExtractor} to use to retrieve the native connection if necessary
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.tableMetaDataContext.setNativeJdbcExtractor(nativeJdbcExtractor);
}
/**
* Get the insert string to be used.
*/

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.
@ -23,7 +23,6 @@ import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
/**
* A SimpleJdbcInsert is a multi-threaded, reusable object providing easy insert
@ -111,12 +110,6 @@ public class SimpleJdbcInsert extends AbstractJdbcInsert implements SimpleJdbcIn
return this;
}
@Override
public SimpleJdbcInsertOperations useNativeJdbcExtractorForMetaData(NativeJdbcExtractor nativeJdbcExtractor) {
setNativeJdbcExtractor(nativeJdbcExtractor);
return this;
}
@Override
public int execute(Map<String, ?> args) {
return doExecute(args);

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.
@ -20,7 +20,6 @@ import java.util.Map;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
/**
* Interface specifying the API for a Simple JDBC Insert implemented by {@link SimpleJdbcInsert}.
@ -82,16 +81,6 @@ public interface SimpleJdbcInsertOperations {
*/
SimpleJdbcInsertOperations includeSynonymsForTableColumnMetaData();
/**
* Use a the provided NativeJdbcExtractor during the column meta data
* lookups via JDBC.
* Note: this is only necessary to include when running with a connection pool
* that wraps the meta data connection and when using a database like Oracle
* where it is necessary to access the native connection to include synonyms.
* @return the instance of this SimpleJdbcInsert
*/
SimpleJdbcInsertOperations useNativeJdbcExtractorForMetaData(NativeJdbcExtractor nativeJdbcExtractor);
/**
* Execute the insert using the values passed in.

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.
@ -85,7 +85,7 @@ public class JdbcBeanDefinitionReader {
/**
* Set the JdbcTemplate to be used by this bean factory.
* Contains settings for DataSource, SQLExceptionTranslator, NativeJdbcExtractor, etc.
* Contains settings for DataSource, SQLExceptionTranslator, etc.
*/
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
Assert.notNull(jdbcTemplate, "JdbcTemplate must not be null");

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.
@ -23,10 +23,8 @@ import java.sql.Connection;
* Connection proxies. Allows access to the underlying target Connection.
*
* <p>This interface can be checked when there is a need to cast to a
* native JDBC Connection such as Oracle's OracleConnection. Spring's
* {@link org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractorAdapter}
* automatically detects such proxies before delegating to the actual
* unwrapping for a specific connection pool.
* native JDBC Connection such as Oracle's OracleConnection. Alternatively,
* all such connections also support JDBC 4.0's {@link Connection#unwrap}.
*
* @author Juergen Hoeller
* @since 1.1

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.
@ -68,11 +68,8 @@ import org.springframework.core.Constants;
*
* <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.
* lazy fetching of an actual JDBC Connection. Use {@link Connection#unwrap}
* to retrieve the native JDBC Connection.
*
* @author Juergen Hoeller
* @since 1.1.4

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.
@ -39,9 +39,6 @@ import org.springframework.util.ObjectUtils;
* <p>If client code will call {@code close()} in the assumption of a pooled
* Connection, like when using persistence tools, set "suppressClose" to "true".
* This will return a close-suppressing proxy instead of the physical Connection.
* Be aware that you will not be able to cast this to a native
* {@code OracleConnection} or the like anymore; you need to use a
* {@link org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor} then.
*
* <p>This is primarily intended for testing. For example, it enables easy testing
* outside an application server, for code that expects to work on a DataSource.
@ -53,10 +50,8 @@ import org.springframework.util.ObjectUtils;
* @see #getConnection()
* @see java.sql.Connection#close()
* @see DataSourceUtils#releaseConnection
* @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor
*/
public class SingleConnectionDataSource extends DriverManagerDataSource
implements SmartDataSource, DisposableBean {
public class SingleConnectionDataSource extends DriverManagerDataSource implements SmartDataSource, DisposableBean {
/** Create a close-suppressing proxy? */
private boolean suppressClose;

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.
@ -61,13 +61,9 @@ import org.springframework.util.Assert;
* that all operations performed through standard JDBC will automatically participate
* in Spring-managed transaction timeouts.
*
* <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 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.
* <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. Use {@link Connection#unwrap} to retrieve the native JDBC Connection.
*
* @author Juergen Hoeller
* @since 1.1

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.
@ -157,7 +157,6 @@ public abstract class SqlCall extends RdbmsOperation {
this.callableStatementFactory = new CallableStatementCreatorFactory(getCallString(), getDeclaredParameters());
this.callableStatementFactory.setResultSetType(getResultSetType());
this.callableStatementFactory.setUpdatableResults(isUpdatableResults());
this.callableStatementFactory.setNativeJdbcExtractor(getJdbcTemplate().getNativeJdbcExtractor());
onCompileInternal();
}

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.
@ -60,7 +60,6 @@ public abstract class SqlOperation extends RdbmsOperation {
if (getGeneratedKeysColumnNames() != null) {
this.preparedStatementFactory.setGeneratedKeysColumnNames(getGeneratedKeysColumnNames());
}
this.preparedStatementFactory.setNativeJdbcExtractor(getJdbcTemplate().getNativeJdbcExtractor());
onCompileInternal();
}

View File

@ -412,7 +412,7 @@ public abstract class JdbcUtils {
/**
* Extract a common name for the database in use even if various drivers/platforms provide varying names.
* @param source the name as provided in database metedata
* @param source the name as provided in database metadata
* @return the common name to be used
*/
public static String commonDatabaseName(String source) {

View File

@ -1,113 +0,0 @@
/*
* Copyright 2002-2012 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.nativejdbc;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.C3P0ProxyConnection;
import org.springframework.util.ReflectionUtils;
/**
* Implementation of the {@link NativeJdbcExtractor} interface for the
* C3P0 connection pool.
*
* <p>Returns underlying native Connections to application code instead of C3P0's
* wrapper implementations; unwraps the Connection for native Statements.
* The returned JDBC classes can then safely be cast, e.g. to
* {@code oracle.jdbc.OracleConnection}.
*
* <p>This NativeJdbcExtractor can be set just to <i>allow</i> working with
* a C3P0 DataSource: If a given object is not a C3P0 wrapper, it will be
* returned as-is.
*
* <p>Note that this class requires C3P0 0.8.5 or later; for earlier C3P0 versions,
* use SimpleNativeJdbcExtractor (which won't work for C3P0 0.8.5 or later).
*
* @author Juergen Hoeller
* @since 1.1.5
* @see com.mchange.v2.c3p0.C3P0ProxyConnection#rawConnectionOperation
* @see SimpleNativeJdbcExtractor
*/
public class C3P0NativeJdbcExtractor extends NativeJdbcExtractorAdapter {
private final Method getRawConnectionMethod;
/**
* This method is not meant to be used directly; it rather serves
* as callback method for C3P0's "rawConnectionOperation" API.
* @param con a native Connection handle
* @return the native Connection handle, as-is
*/
public static Connection getRawConnection(Connection con) {
return con;
}
public C3P0NativeJdbcExtractor() {
try {
this.getRawConnectionMethod = getClass().getMethod("getRawConnection", new Class<?>[] {Connection.class});
}
catch (NoSuchMethodException ex) {
throw new IllegalStateException("Internal error in C3P0NativeJdbcExtractor: " + ex.getMessage());
}
}
@Override
public boolean isNativeConnectionNecessaryForNativeStatements() {
return true;
}
@Override
public boolean isNativeConnectionNecessaryForNativePreparedStatements() {
return true;
}
@Override
public boolean isNativeConnectionNecessaryForNativeCallableStatements() {
return true;
}
/**
* Retrieve the Connection via C3P0's {@code rawConnectionOperation} API,
* using the {@code getRawConnection} as callback to get access to the
* raw Connection (which is otherwise not directly supported by C3P0).
* @see #getRawConnection
*/
@Override
protected Connection doGetNativeConnection(Connection con) throws SQLException {
if (con instanceof C3P0ProxyConnection) {
C3P0ProxyConnection cpCon = (C3P0ProxyConnection) con;
try {
return (Connection) cpCon.rawConnectionOperation(
this.getRawConnectionMethod, null, new Object[] {C3P0ProxyConnection.RAW_CONNECTION});
}
catch (SQLException ex) {
throw ex;
}
catch (Exception ex) {
ReflectionUtils.handleReflectionException(ex);
}
}
return con;
}
}

View File

@ -1,159 +0,0 @@
/*
* Copyright 2002-2012 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.nativejdbc;
import java.lang.reflect.Method;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.springframework.util.ReflectionUtils;
/**
* Implementation of the {@link NativeJdbcExtractor} interface for JBoss,
* supporting JBoss Application Server 3.2.4+. As of Spring 3.1.1, it also
* supports JBoss 7.
*
* <p>Returns the underlying native Connection, Statement, etc to
* application code instead of JBoss' wrapper implementations.
* The returned JDBC classes can then safely be cast, e.g. to
* {@code oracle.jdbc.OracleConnection}.
*
* <p>This NativeJdbcExtractor can be set just to <i>allow</i> working with
* a JBoss connection pool: If a given object is not a JBoss wrapper,
* it will be returned as-is.
*
* @author Juergen Hoeller
* @since 03.01.2004
* @see org.jboss.resource.adapter.jdbc.WrappedConnection#getUnderlyingConnection
* @see org.jboss.resource.adapter.jdbc.WrappedStatement#getUnderlyingStatement
* @see org.jboss.resource.adapter.jdbc.WrappedResultSet#getUnderlyingResultSet
*/
public class JBossNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
// JBoss 7
private static final String JBOSS_JCA_PREFIX = "org.jboss.jca.adapters.jdbc.";
// JBoss <= 6
private static final String JBOSS_RESOURCE_PREFIX = "org.jboss.resource.adapter.jdbc.";
private Class<?> wrappedConnectionClass;
private Class<?> wrappedStatementClass;
private Class<?> wrappedResultSetClass;
private Method getUnderlyingConnectionMethod;
private Method getUnderlyingStatementMethod;
private Method getUnderlyingResultSetMethod;
/**
* This constructor retrieves JBoss JDBC wrapper classes,
* so we can get the underlying vendor connection using reflection.
*/
public JBossNativeJdbcExtractor() {
String prefix = JBOSS_JCA_PREFIX;
try {
// trying JBoss 7 jca package first...
this.wrappedConnectionClass = getClass().getClassLoader().loadClass(prefix + "WrappedConnection");
}
catch (ClassNotFoundException ex) {
// JBoss 7 jca package not found -> try traditional resource package.
prefix = JBOSS_RESOURCE_PREFIX;
try {
this.wrappedConnectionClass = getClass().getClassLoader().loadClass(prefix + "WrappedConnection");
}
catch (ClassNotFoundException ex2) {
throw new IllegalStateException("Could not initialize JBossNativeJdbcExtractor: neither JBoss 7's [" +
JBOSS_JCA_PREFIX + ".WrappedConnection] nor traditional JBoss [" + JBOSS_RESOURCE_PREFIX +
".WrappedConnection] found");
}
}
try {
this.wrappedStatementClass = getClass().getClassLoader().loadClass(prefix + "WrappedStatement");
this.wrappedResultSetClass = getClass().getClassLoader().loadClass(prefix + "WrappedResultSet");
this.getUnderlyingConnectionMethod =
this.wrappedConnectionClass.getMethod("getUnderlyingConnection", (Class[]) null);
this.getUnderlyingStatementMethod =
this.wrappedStatementClass.getMethod("getUnderlyingStatement", (Class[]) null);
this.getUnderlyingResultSetMethod =
this.wrappedResultSetClass.getMethod("getUnderlyingResultSet", (Class[]) null);
}
catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize JBossNativeJdbcExtractor because of missing JBoss API methods/classes: " + ex);
}
}
/**
* Retrieve the Connection via JBoss' {@code getUnderlyingConnection} method.
*/
@Override
protected Connection doGetNativeConnection(Connection con) throws SQLException {
if (this.wrappedConnectionClass.isAssignableFrom(con.getClass())) {
return (Connection) ReflectionUtils.invokeJdbcMethod(this.getUnderlyingConnectionMethod, con);
}
return con;
}
/**
* Retrieve the Connection via JBoss' {@code getUnderlyingStatement} method.
*/
@Override
public Statement getNativeStatement(Statement stmt) throws SQLException {
if (this.wrappedStatementClass.isAssignableFrom(stmt.getClass())) {
return (Statement) ReflectionUtils.invokeJdbcMethod(this.getUnderlyingStatementMethod, stmt);
}
return stmt;
}
/**
* Retrieve the Connection via JBoss' {@code getUnderlyingStatement} method.
*/
@Override
public PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException {
return (PreparedStatement) getNativeStatement(ps);
}
/**
* Retrieve the Connection via JBoss' {@code getUnderlyingStatement} method.
*/
@Override
public CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException {
return (CallableStatement) getNativeStatement(cs);
}
/**
* Retrieve the Connection via JBoss' {@code getUnderlyingResultSet} method.
*/
@Override
public ResultSet getNativeResultSet(ResultSet rs) throws SQLException {
if (this.wrappedResultSetClass.isAssignableFrom(rs.getClass())) {
return (ResultSet) ReflectionUtils.invokeJdbcMethod(this.getUnderlyingResultSetMethod, rs);
}
return rs;
}
}

View File

@ -1,120 +0,0 @@
/*
* Copyright 2002-2012 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.nativejdbc;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* {@link NativeJdbcExtractor} implementation that delegates to JDBC 4.0's
* {@code unwrap} method, as defined by {@link java.sql.Wrapper}.
* You will typically need to specify a vendor {@link #setConnectionType Connection type}
* / {@link #setStatementType Statement type} / {@link #setResultSetType ResultSet type}
* to extract, since JDBC 4.0 only actually unwraps to a given target type.
*
* <p>Note: Only use this when actually running against a JDBC 4.0 driver, with a
* connection pool that supports the JDBC 4.0 API (i.e. at least accepts JDBC 4.0
* API calls and passes them through to the underlying driver)! Other than that,
* there is no need for connection pool specific setup. As of JDBC 4.0,
* NativeJdbcExtractors will typically be implemented for specific drivers
* instead of for specific pools (e.g. {@link OracleJdbc4NativeJdbcExtractor}).
*
* @author Juergen Hoeller
* @since 2.5
* @see java.sql.Wrapper#unwrap
* @see SimpleNativeJdbcExtractor
* @see org.springframework.jdbc.core.JdbcTemplate#setNativeJdbcExtractor
*/
public class Jdbc4NativeJdbcExtractor extends NativeJdbcExtractorAdapter {
private Class<? extends Connection> connectionType = Connection.class;
private Class<? extends Statement> statementType = Statement.class;
private Class<? extends PreparedStatement> preparedStatementType = PreparedStatement.class;
private Class<? extends CallableStatement> callableStatementType = CallableStatement.class;
private Class<? extends ResultSet> resultSetType = ResultSet.class;
/**
* Set the vendor's Connection type, e.g. {@code oracle.jdbc.OracleConnection}.
*/
public void setConnectionType(Class<? extends Connection> connectionType) {
this.connectionType = connectionType;
}
/**
* Set the vendor's Statement type, e.g. {@code oracle.jdbc.OracleStatement}.
*/
public void setStatementType(Class<? extends Statement> statementType) {
this.statementType = statementType;
}
/**
* Set the vendor's PreparedStatement type, e.g. {@code oracle.jdbc.OraclePreparedStatement}.
*/
public void setPreparedStatementType(Class<? extends PreparedStatement> preparedStatementType) {
this.preparedStatementType = preparedStatementType;
}
/**
* Set the vendor's CallableStatement type, e.g. {@code oracle.jdbc.OracleCallableStatement}.
*/
public void setCallableStatementType(Class<? extends CallableStatement> callableStatementType) {
this.callableStatementType = callableStatementType;
}
/**
* Set the vendor's ResultSet type, e.g. {@code oracle.jdbc.OracleResultSet}.
*/
public void setResultSetType(Class<? extends ResultSet> resultSetType) {
this.resultSetType = resultSetType;
}
@Override
protected Connection doGetNativeConnection(Connection con) throws SQLException {
return con.unwrap(this.connectionType);
}
@Override
public Statement getNativeStatement(Statement stmt) throws SQLException {
return stmt.unwrap(this.statementType);
}
@Override
public PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException {
return ps.unwrap(this.preparedStatementType);
}
@Override
public CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException {
return cs.unwrap(this.callableStatementType);
}
@Override
public ResultSet getNativeResultSet(ResultSet rs) throws SQLException {
return rs.unwrap(this.resultSetType);
}
}

View File

@ -1,157 +0,0 @@
/*
* Copyright 2002-2016 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.nativejdbc;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Interface for extracting native JDBC objects from wrapped objects coming from
* connection pools. This is necessary to allow for casting to native implementations
* like {@code OracleConnection} or {@code OracleResultSet} in application
* code, for example to create Blobs or to access vendor-specific features.
*
* <p>Note: Setting a custom {@code NativeJdbcExtractor} is just necessary
* if you intend to cast to database-specific implementations like
* {@code OracleConnection} or {@code OracleResultSet}.
* Otherwise, any wrapped JDBC object will be fine, with no need for unwrapping.
*
* <p>Note: To be able to support any pool's strategy of native ResultSet wrapping,
* it is advisable to get both the native Statement <i>and</i> the native ResultSet
* via this extractor. Some pools just allow to unwrap the Statement, some just to
* unwrap the ResultSet - the above strategy will cover both. It is typically
* <i>not</i> necessary to unwrap the Connection to retrieve a native ResultSet.
*
* <p>When working with a simple connection pool that wraps Connections but not
* Statements, a {@link SimpleNativeJdbcExtractor} is often sufficient.
*
* <p>{@link org.springframework.jdbc.core.JdbcTemplate} can properly apply a
* {@code NativeJdbcExtractor} if specified, unwrapping all JDBC objects
* that it creates. Note that this is just necessary if you intend to cast to
* native implementations in your data access code.
*
* @author Juergen Hoeller
* @since 25.08.2003
* @see SimpleNativeJdbcExtractor
* @see org.springframework.jdbc.core.JdbcTemplate#setNativeJdbcExtractor
*/
public interface NativeJdbcExtractor {
/**
* Return whether it is necessary to work on the native Connection to
* receive native Statements.
* <p>This should be true if the connection pool does not allow to extract
* the native JDBC objects from its Statement wrapper but supports a way
* to retrieve the native JDBC Connection. This way, applications can
* still receive native Statements and ResultSet via working on the
* native JDBC Connection.
*/
boolean isNativeConnectionNecessaryForNativeStatements();
/**
* Return whether it is necessary to work on the native Connection to
* receive native PreparedStatements.
* <p>This should be true if the connection pool does not allow to extract
* the native JDBC objects from its PreparedStatement wrappers but
* supports a way to retrieve the native JDBC Connection. This way,
* applications can still receive native Statements and ResultSet via
* working on the native JDBC Connection.
*/
boolean isNativeConnectionNecessaryForNativePreparedStatements();
/**
* Return whether it is necessary to work on the native Connection to
* receive native CallableStatements.
* <p>This should be true if the connection pool does not allow to extract
* the native JDBC objects from its CallableStatement wrappers but
* supports a way to retrieve the native JDBC Connection. This way,
* applications can still receive native Statements and ResultSet via
* working on the native JDBC Connection.
*/
boolean isNativeConnectionNecessaryForNativeCallableStatements();
/**
* Retrieve the underlying native JDBC Connection for the given Connection.
* Supposed to return the given Connection if not capable of unwrapping.
* @param con the Connection handle, potentially wrapped by a connection pool
* @return the underlying native JDBC Connection, if possible;
* else, the original Connection
* @throws SQLException if thrown by JDBC methods
*/
Connection getNativeConnection(Connection con) throws SQLException;
/**
* Retrieve the underlying native JDBC Connection for the given Statement.
* Supposed to return the {@code Statement.getConnection()} if not
* capable of unwrapping.
* <p>Having this extra method allows for more efficient unwrapping if data
* access code already has a Statement. {@code Statement.getConnection()}
* often returns the native JDBC Connection even if the Statement itself
* is wrapped by a pool.
* @param stmt the Statement handle, potentially wrapped by a connection pool
* @return the underlying native JDBC Connection, if possible;
* else, the original Connection
* @throws SQLException if thrown by JDBC methods
* @see java.sql.Statement#getConnection()
*/
Connection getNativeConnectionFromStatement(Statement stmt) throws SQLException;
/**
* Retrieve the underlying native JDBC Statement for the given Statement.
* Supposed to return the given Statement if not capable of unwrapping.
* @param stmt the Statement handle, potentially wrapped by a connection pool
* @return the underlying native JDBC Statement, if possible;
* else, the original Statement
* @throws SQLException if thrown by JDBC methods
*/
Statement getNativeStatement(Statement stmt) throws SQLException;
/**
* Retrieve the underlying native JDBC PreparedStatement for the given statement.
* Supposed to return the given PreparedStatement if not capable of unwrapping.
* @param ps the PreparedStatement handle, potentially wrapped by a connection pool
* @return the underlying native JDBC PreparedStatement, if possible;
* else, the original PreparedStatement
* @throws SQLException if thrown by JDBC methods
*/
PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException;
/**
* Retrieve the underlying native JDBC CallableStatement for the given statement.
* Supposed to return the given CallableStatement if not capable of unwrapping.
* @param cs the CallableStatement handle, potentially wrapped by a connection pool
* @return the underlying native JDBC CallableStatement, if possible;
* else, the original CallableStatement
* @throws SQLException if thrown by JDBC methods
*/
CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException;
/**
* Retrieve the underlying native JDBC ResultSet for the given statement.
* Supposed to return the given ResultSet if not capable of unwrapping.
* @param rs the ResultSet handle, potentially wrapped by a connection pool
* @return the underlying native JDBC ResultSet, if possible;
* else, the original ResultSet
* @throws SQLException if thrown by JDBC methods
*/
ResultSet getNativeResultSet(ResultSet rs) throws SQLException;
}

View File

@ -1,175 +0,0 @@
/*
* Copyright 2002-2012 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.nativejdbc;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.springframework.jdbc.datasource.DataSourceUtils;
/**
* Abstract adapter class for the {@link NativeJdbcExtractor} interface,
* for simplified implementation of basic extractors.
* Basically returns the passed-in JDBC objects on all methods.
*
* <p>{@code getNativeConnection} checks for a ConnectionProxy chain,
* for example from a TransactionAwareDataSourceProxy, before delegating to
* {@code doGetNativeConnection} for actual unwrapping. You can override
* either of the two for a specific connection pool, but the latter is
* recommended to participate in ConnectionProxy unwrapping.
*
* <p>{@code getNativeConnection} also applies a fallback if the first
* native extraction process failed, that is, returned the same Connection as
* passed in. It assumes that some additional proxying is going in this case:
* Hence, it retrieves the underlying native Connection from the DatabaseMetaData
* via {@code conHandle.getMetaData().getConnection()} and retries the native
* extraction process based on that Connection handle. This works, for example,
* for the Connection proxies exposed by Hibernate 3.1's {@code Session.connection()}.
*
* <p>The {@code getNativeConnectionFromStatement} method is implemented
* to simply delegate to {@code getNativeConnection} with the Statement's
* Connection. This is what most extractor implementations will stick to,
* unless there's a more efficient version for a specific pool.
*
* @author Juergen Hoeller
* @since 1.1
* @see #getNativeConnection
* @see #getNativeConnectionFromStatement
* @see org.springframework.jdbc.datasource.ConnectionProxy
*/
public abstract class NativeJdbcExtractorAdapter implements NativeJdbcExtractor {
/**
* Return {@code false} by default.
*/
@Override
public boolean isNativeConnectionNecessaryForNativeStatements() {
return false;
}
/**
* Return {@code false} by default.
*/
@Override
public boolean isNativeConnectionNecessaryForNativePreparedStatements() {
return false;
}
/**
* Return {@code false} by default.
*/
@Override
public boolean isNativeConnectionNecessaryForNativeCallableStatements() {
return false;
}
/**
* Check for a ConnectionProxy chain, then delegate to doGetNativeConnection.
* <p>ConnectionProxy is used by Spring's TransactionAwareDataSourceProxy
* and LazyConnectionDataSourceProxy. The target connection behind it is
* typically one from a local connection pool, to be unwrapped by the
* doGetNativeConnection implementation of a concrete subclass.
* @see #doGetNativeConnection
* @see org.springframework.jdbc.datasource.ConnectionProxy
* @see org.springframework.jdbc.datasource.DataSourceUtils#getTargetConnection
* @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy
* @see org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy
*/
@Override
public Connection getNativeConnection(Connection con) throws SQLException {
if (con == null) {
return null;
}
Connection targetCon = DataSourceUtils.getTargetConnection(con);
Connection nativeCon = doGetNativeConnection(targetCon);
if (nativeCon == targetCon) {
// We haven't received a different Connection, so we'll assume that there's
// some additional proxying going on. Let's check whether we get something
// different back from the DatabaseMetaData.getConnection() call.
DatabaseMetaData metaData = targetCon.getMetaData();
// The following check is only really there for mock Connections
// which might not carry a DatabaseMetaData instance.
if (metaData != null) {
Connection metaCon = metaData.getConnection();
if (metaCon != null && metaCon != targetCon) {
// We've received a different Connection there:
// Let's retry the native extraction process with it.
nativeCon = doGetNativeConnection(metaCon);
}
}
}
return nativeCon;
}
/**
* Not able to unwrap: return passed-in Connection.
*/
protected Connection doGetNativeConnection(Connection con) throws SQLException {
return con;
}
/**
* Retrieve the Connection via the Statement's Connection.
* @see #getNativeConnection
* @see Statement#getConnection
*/
@Override
public Connection getNativeConnectionFromStatement(Statement stmt) throws SQLException {
if (stmt == null) {
return null;
}
return getNativeConnection(stmt.getConnection());
}
/**
* Not able to unwrap: return passed-in Statement.
*/
@Override
public Statement getNativeStatement(Statement stmt) throws SQLException {
return stmt;
}
/**
* Not able to unwrap: return passed-in PreparedStatement.
*/
@Override
public PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException {
return ps;
}
/**
* Not able to unwrap: return passed-in CallableStatement.
*/
@Override
public CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException {
return cs;
}
/**
* Not able to unwrap: return passed-in ResultSet.
*/
@Override
public ResultSet getNativeResultSet(ResultSet rs) throws SQLException {
return rs;
}
}

View File

@ -1,60 +0,0 @@
/*
* Copyright 2002-2012 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.nativejdbc;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
/**
* A {@link Jdbc4NativeJdbcExtractor} which comes pre-configured for Oracle's JDBC driver,
* specifying the following vendor-specific API types for unwrapping:
* <ul>
* <li>{@code oracle.jdbc.OracleConnection}
* <li>{@code oracle.jdbc.OracleStatement}
* <li>{@code oracle.jdbc.OraclePreparedStatement}
* <li>{@code oracle.jdbc.OracleCallableStatement}
* <li>{@code oracle.jdbc.OracleResultSet}
* </ul>
*
* <p>Note: This will work with any JDBC 4.0 compliant connection pool, without a need for
* connection pool specific setup. In other words, as of JDBC 4.0, NativeJdbcExtractors
* will typically be implemented for specific drivers instead of for specific pools.
*
* @author Juergen Hoeller
* @since 3.0.5
*/
public class OracleJdbc4NativeJdbcExtractor extends Jdbc4NativeJdbcExtractor {
@SuppressWarnings("unchecked")
public OracleJdbc4NativeJdbcExtractor() {
try {
setConnectionType((Class<Connection>) getClass().getClassLoader().loadClass("oracle.jdbc.OracleConnection"));
setStatementType((Class<Statement>) getClass().getClassLoader().loadClass("oracle.jdbc.OracleStatement"));
setPreparedStatementType((Class<PreparedStatement>) getClass().getClassLoader().loadClass("oracle.jdbc.OraclePreparedStatement"));
setCallableStatementType((Class<CallableStatement>) getClass().getClassLoader().loadClass("oracle.jdbc.OracleCallableStatement"));
setResultSetType((Class<ResultSet>) getClass().getClassLoader().loadClass("oracle.jdbc.OracleResultSet"));
}
catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize OracleJdbc4NativeJdbcExtractor because Oracle API classes are not available: " + ex);
}
}
}

View File

@ -1,129 +0,0 @@
/*
* Copyright 2002-2016 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.nativejdbc;
/**
* A simple implementation of the {@link NativeJdbcExtractor} interface.
* Assumes a pool that wraps Connection handles but not DatabaseMetaData:
* In this case, the underlying native Connection can be retrieved by simply
* calling {@code conHandle.getMetaData().getConnection()}.
* All other JDBC objects will be returned as passed in.
*
* <p>This extractor should work with any pool that does not wrap DatabaseMetaData,
* and will also work with any plain JDBC driver. Note that a pool can still wrap
* Statements, PreparedStatements, etc: The only requirement of this extractor is
* that {@code java.sql.DatabaseMetaData} does not get wrapped, returning the
* native Connection of the JDBC driver on {@code metaData.getConnection()}.
*
* <p>Customize this extractor by setting the "nativeConnectionNecessaryForXxx"
* flags accordingly: If Statements, PreparedStatements, and/or CallableStatements
* are wrapped by your pool, set the corresponding "nativeConnectionNecessaryForXxx"
* flags to "true". If none of the statement types is wrapped - or you solely need
* Connection unwrapping in the first place -, the defaults are fine.
*
* <p>For full usage with JdbcTemplate, i.e. to also provide Statement unwrapping:
* <ul>
* <li>Use a default SimpleNativeJdbcExtractor for Resin and SJSAS (no JDBC
* Statement objects are wrapped, therefore no special unwrapping is necessary).
* <li>Use a SimpleNativeJdbcExtractor with all "nativeConnectionNecessaryForXxx"
* flags set to "true" for C3P0 (all JDBC Statement objects are wrapped,
* but none of the wrappers allow for unwrapping).
* <li>Use a JBossNativeJdbcExtractor for JBoss (all JDBC Statement objects are
* wrapped, but all of them can be extracted by casting to implementation classes).
* </ul>
*
* @author Juergen Hoeller
* @since 05.12.2003
* @see #setNativeConnectionNecessaryForNativeStatements
* @see #setNativeConnectionNecessaryForNativePreparedStatements
* @see #setNativeConnectionNecessaryForNativeCallableStatements
* @see Jdbc4NativeJdbcExtractor
* @see org.springframework.jdbc.core.JdbcTemplate#setNativeJdbcExtractor
*/
public class SimpleNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
private boolean nativeConnectionNecessaryForNativeStatements = false;
private boolean nativeConnectionNecessaryForNativePreparedStatements = false;
private boolean nativeConnectionNecessaryForNativeCallableStatements = false;
/**
* Set whether it is necessary to work on the native Connection to
* receive native Statements. Default is "false". If true, the Connection
* will be unwrapped first to create a Statement.
* <p>This makes sense if you need to work with native Statements from
* a pool that does not allow to extract the native JDBC objects from its
* wrappers but returns the native Connection on DatabaseMetaData.getConnection.
* <p>The standard SimpleNativeJdbcExtractor is unable to unwrap statements,
* so set this to true if your connection pool wraps Statements.
* @see java.sql.Connection#createStatement
* @see java.sql.DatabaseMetaData#getConnection
*/
public void setNativeConnectionNecessaryForNativeStatements(boolean nativeConnectionNecessaryForNativeStatements) {
this.nativeConnectionNecessaryForNativeStatements = nativeConnectionNecessaryForNativeStatements;
}
@Override
public boolean isNativeConnectionNecessaryForNativeStatements() {
return this.nativeConnectionNecessaryForNativeStatements;
}
/**
* Set whether it is necessary to work on the native Connection to
* receive native PreparedStatements. Default is "false". If true,
* the Connection will be unwrapped first to create a PreparedStatement.
* <p>This makes sense if you need to work with native PreparedStatements from
* a pool that does not allow to extract the native JDBC objects from its
* wrappers but returns the native Connection on Statement.getConnection.
* <p>The standard SimpleNativeJdbcExtractor is unable to unwrap statements,
* so set this to true if your connection pool wraps PreparedStatements.
* @see java.sql.Connection#prepareStatement
* @see java.sql.DatabaseMetaData#getConnection
*/
public void setNativeConnectionNecessaryForNativePreparedStatements(boolean nativeConnectionNecessary) {
this.nativeConnectionNecessaryForNativePreparedStatements = nativeConnectionNecessary;
}
@Override
public boolean isNativeConnectionNecessaryForNativePreparedStatements() {
return this.nativeConnectionNecessaryForNativePreparedStatements;
}
/**
* Set whether it is necessary to work on the native Connection to
* receive native CallableStatements. Default is "false". If true,
* the Connection will be unwrapped first to create a CallableStatement.
* <p>This makes sense if you need to work with native CallableStatements from
* a pool that does not allow to extract the native JDBC objects from its
* wrappers but returns the native Connection on Statement.getConnection.
* <p>The standard SimpleNativeJdbcExtractor is unable to unwrap statements,
* so set this to true if your connection pool wraps CallableStatements.
* @see java.sql.Connection#prepareCall
* @see java.sql.DatabaseMetaData#getConnection
*/
public void setNativeConnectionNecessaryForNativeCallableStatements(boolean nativeConnectionNecessary) {
this.nativeConnectionNecessaryForNativeCallableStatements = nativeConnectionNecessary;
}
@Override
public boolean isNativeConnectionNecessaryForNativeCallableStatements() {
return this.nativeConnectionNecessaryForNativeCallableStatements;
}
}

View File

@ -1,105 +0,0 @@
/*
* 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.nativejdbc;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import org.springframework.util.ReflectionUtils;
/**
* Implementation of the {@link NativeJdbcExtractor} interface for WebLogic,
* 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
* statements. The returned JDBC classes can then safely be cast, e.g. to
* {@code oracle.jdbc.OracleConnection}.
*
* <p>This NativeJdbcExtractor can be set just to <i>allow</i> working
* with a WebLogic DataSource: If a given object is not a WebLogic
* Connection wrapper, it will be returned as-is.
*
* @author Thomas Risberg
* @author Juergen Hoeller
* @since 1.0.2
* @see #getNativeConnection
* @see weblogic.jdbc.extensions.WLConnection#getVendorConnection
*/
public class WebLogicNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
private static final String JDBC_EXTENSION_NAME = "weblogic.jdbc.extensions.WLConnection";
private final Class<?> jdbcExtensionClass;
private final Method getVendorConnectionMethod;
/**
* This constructor retrieves the WebLogic JDBC extension interface,
* so we can get the underlying vendor connection using reflection.
*/
public WebLogicNativeJdbcExtractor() {
try {
this.jdbcExtensionClass = getClass().getClassLoader().loadClass(JDBC_EXTENSION_NAME);
this.getVendorConnectionMethod = this.jdbcExtensionClass.getMethod("getVendorConnection", (Class[]) null);
}
catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize WebLogicNativeJdbcExtractor because WebLogic API classes are not available: " + ex);
}
}
/**
* Return {@code true}, as WebLogic returns wrapped Statements.
*/
@Override
public boolean isNativeConnectionNecessaryForNativeStatements() {
return true;
}
/**
* Return {@code true}, as WebLogic returns wrapped PreparedStatements.
*/
@Override
public boolean isNativeConnectionNecessaryForNativePreparedStatements() {
return true;
}
/**
* Return {@code true}, as WebLogic returns wrapped CallableStatements.
*/
@Override
public boolean isNativeConnectionNecessaryForNativeCallableStatements() {
return true;
}
/**
* Retrieve the Connection via WebLogic's {@code getVendorConnection} method.
*/
@Override
protected Connection doGetNativeConnection(Connection con) throws SQLException {
if (this.jdbcExtensionClass.isAssignableFrom(con.getClass())) {
return (Connection) ReflectionUtils.invokeJdbcMethod(this.getVendorConnectionMethod, con);
}
return con;
}
}

View File

@ -1,106 +0,0 @@
/*
* 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.nativejdbc;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import org.springframework.util.ReflectionUtils;
/**
* Implementation of the {@link NativeJdbcExtractor} interface for WebSphere,
* 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
* native statements. The returned JDBC classes can then safely be cast,
* e.g. to {@code oracle.jdbc.OracleConnection}.
*
* <p>This NativeJdbcExtractor can be set just to <i>allow</i> working
* with a WebSphere DataSource: If a given object is not a WebSphere
* Connection wrapper, it will be returned as-is.
*
* @author Juergen Hoeller
* @since 1.1
*/
public class WebSphereNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
private static final String JDBC_ADAPTER_CONNECTION_NAME = "com.ibm.ws.rsadapter.jdbc.WSJdbcConnection";
private static final String JDBC_ADAPTER_UTIL_NAME = "com.ibm.ws.rsadapter.jdbc.WSJdbcUtil";
private Class<?> webSphereConnectionClass;
private Method webSphereNativeConnectionMethod;
/**
* This constructor retrieves WebSphere JDBC adapter classes,
* so we can get the underlying vendor connection using reflection.
*/
public WebSphereNativeJdbcExtractor() {
try {
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(
"Could not initialize WebSphereNativeJdbcExtractor because WebSphere API classes are not available: " + ex);
}
}
/**
* Return {@code true}, as WebSphere returns wrapped Statements.
*/
@Override
public boolean isNativeConnectionNecessaryForNativeStatements() {
return true;
}
/**
* Return {@code true}, as WebSphere returns wrapped PreparedStatements.
*/
@Override
public boolean isNativeConnectionNecessaryForNativePreparedStatements() {
return true;
}
/**
* Return {@code true}, as WebSphere returns wrapped CallableStatements.
*/
@Override
public boolean isNativeConnectionNecessaryForNativeCallableStatements() {
return true;
}
/**
* Retrieve the Connection via WebSphere's {@code getNativeConnection} method.
*/
@Override
protected Connection doGetNativeConnection(Connection con) throws SQLException {
if (this.webSphereConnectionClass.isAssignableFrom(con.getClass())) {
return (Connection) ReflectionUtils.invokeJdbcMethod(this.webSphereNativeConnectionMethod, null, con);
}
return con;
}
}

View File

@ -1,7 +0,0 @@
/**
* Provides a mechanism for extracting native implementations of JDBC
* interfaces from wrapper objects that got returned from connection pools.
*
* <p>Can be used independently, for example in custom JDBC access code.
*/
package org.springframework.jdbc.support.nativejdbc;

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,8 +48,6 @@ import org.springframework.jdbc.core.support.AbstractInterruptibleBatchPreparedS
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractorAdapter;
import org.springframework.util.LinkedCaseInsensitiveMap;
import static org.hamcrest.Matchers.*;
@ -295,19 +293,6 @@ public class JdbcTemplateTests {
verify(this.preparedStatement).close();
}
@Test
public void testConnectionCallback() throws Exception {
this.template.setNativeJdbcExtractor(new PlainNativeJdbcExtractor());
String result = this.template.execute(new ConnectionCallback<String>() {
@Override
public String doInConnection(Connection con) {
assertSame(JdbcTemplateTests.this.connection, con);
return "test";
}
});
assertEquals("test", result);
}
@Test
public void testConnectionCallbackWithStatementSettings() throws Exception {
String result = this.template.execute(new ConnectionCallback<String>() {
@ -317,7 +302,6 @@ public class JdbcTemplateTests {
ps.setFetchSize(10);
ps.setMaxRows(20);
ps.close();
assertSame(JdbcTemplateTests.this.connection, new PlainNativeJdbcExtractor().getNativeConnection(con));
return "test";
}
});
@ -1096,105 +1080,6 @@ public class JdbcTemplateTests {
}
}
@Test
public void testNativeJdbcExtractorInvoked() throws Exception {
final Statement statement2 = mock(Statement.class);
given(statement2.executeQuery(anyString())).willReturn(this.resultSet);
final PreparedStatement preparedStatement2 = mock(PreparedStatement.class);
given(preparedStatement2.executeQuery()).willReturn(this.resultSet);
final ResultSet returnResultSet = mock(ResultSet.class);
given(returnResultSet.next()).willReturn(false);
final CallableStatement callableStatement = mock(CallableStatement.class);
final CallableStatement callableStatement2 = mock(CallableStatement.class);
given(callableStatement2.execute()).willReturn(true);
given(callableStatement2.getUpdateCount()).willReturn(-1);
given(callableStatement2.getResultSet()).willReturn(returnResultSet);
given(callableStatement2.getUpdateCount()).willReturn(-1);
given(this.connection.createStatement()).willReturn(this.statement);
this.template.setNativeJdbcExtractor(new NativeJdbcExtractor() {
@Override
public boolean isNativeConnectionNecessaryForNativeStatements() {
return false;
}
@Override
public boolean isNativeConnectionNecessaryForNativePreparedStatements() {
return false;
}
@Override
public boolean isNativeConnectionNecessaryForNativeCallableStatements() {
return false;
}
@Override
public Connection getNativeConnection(Connection con) {
return con;
}
@Override
public Connection getNativeConnectionFromStatement(Statement stmt) throws SQLException {
return stmt.getConnection();
}
@Override
public Statement getNativeStatement(Statement stmt) {
assertTrue(stmt == JdbcTemplateTests.this.statement);
return statement2;
}
@Override
public PreparedStatement getNativePreparedStatement(PreparedStatement ps) {
assertTrue(ps == JdbcTemplateTests.this.preparedStatement);
return preparedStatement2;
}
@Override
public CallableStatement getNativeCallableStatement(CallableStatement cs) {
assertTrue(cs == callableStatement);
return callableStatement2;
}
@Override
public ResultSet getNativeResultSet(ResultSet rs) {
return rs;
}
});
this.template.query("my query", new ResultSetExtractor<Object>() {
@Override
public Object extractData(ResultSet rs2) {
assertEquals(JdbcTemplateTests.this.resultSet, rs2);
return null;
}
});
this.template.query(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection conn) {
return JdbcTemplateTests.this.preparedStatement;
}
}, new ResultSetExtractor<Object>() {
@Override
public Object extractData(ResultSet rs2) {
assertEquals(JdbcTemplateTests.this.resultSet, rs2);
return null;
}
});
this.template.call(new CallableStatementCreator() {
@Override
public CallableStatement createCallableStatement(Connection con) {
return callableStatement;
}
}, new ArrayList<>());
verify(this.resultSet, times(2)).close();
verify(this.statement).close();
verify(this.preparedStatement).close();
verify(returnResultSet).close();
verify(callableStatement).close();
verify(this.connection, atLeastOnce()).close();
}
@Test
public void testStaticResultSetClosed() throws Exception {
ResultSet resultSet2 = mock(ResultSet.class);
@ -1311,16 +1196,8 @@ public class JdbcTemplateTests {
given(this.connection.getMetaData()).willReturn(databaseMetaData);
}
private static class PlainNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
@Override
protected Connection doGetNativeConnection(Connection connection) throws SQLException {
return connection;
}
}
private static interface JdbcTemplateCallback {
private interface JdbcTemplateCallback {
void doInJdbcTemplate(JdbcTemplate template, String sql, RowCallbackHandler rch);
}
@ -1329,6 +1206,7 @@ public class JdbcTemplateTests {
private static class Dispatcher implements PreparedStatementCreator, SqlProvider {
private int id;
private String sql;
public Dispatcher(int id, String sql) {
@ -1348,4 +1226,5 @@ public class JdbcTemplateTests {
return this.sql;
}
}
}

View File

@ -31,7 +31,6 @@ import org.mockito.InOrder;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor;
import org.springframework.tests.Assume;
import org.springframework.tests.TestGroup;
import org.springframework.transaction.CannotCreateTransactionException;
@ -142,7 +141,6 @@ public class DataSourceTransactionManagerTests {
try {
if (createStatement) {
tCon.createStatement();
assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(tCon));
}
}
catch (SQLException ex) {
@ -993,7 +991,6 @@ public class DataSourceTransactionManagerTests {
TransactionAwareDataSourceProxy dsProxy = new TransactionAwareDataSourceProxy(ds);
try {
assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection()));
// should be ignored
dsProxy.getConnection().close();
}
@ -1027,7 +1024,6 @@ public class DataSourceTransactionManagerTests {
final TransactionAwareDataSourceProxy dsProxy = new TransactionAwareDataSourceProxy(ds);
try {
assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection()));
// should be ignored
dsProxy.getConnection().close();
}
@ -1042,7 +1038,6 @@ public class DataSourceTransactionManagerTests {
assertEquals(con, DataSourceUtils.getConnection(ds));
try {
assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection()));
// should be ignored
dsProxy.getConnection().close();
}
@ -1088,7 +1083,6 @@ public class DataSourceTransactionManagerTests {
dsProxy.setReobtainTransactionalConnections(true);
try {
assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection()));
// should be ignored
dsProxy.getConnection().close();
}
@ -1103,7 +1097,6 @@ public class DataSourceTransactionManagerTests {
assertEquals(con, DataSourceUtils.getConnection(ds));
try {
assertEquals(con, ((ConnectionProxy) dsProxy.getConnection()).getTargetConnection());
assertEquals(con, new SimpleNativeJdbcExtractor().getNativeConnection(dsProxy.getConnection()));
// should be ignored
dsProxy.getConnection().close();
}

View File

@ -1,78 +0,0 @@
/*
* Copyright 2002-2016 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;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.junit.Test;
import org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
/**
* @author Andre Biryukov
* @author Juergen Hoeller
*/
public class NativeJdbcExtractorTests {
@Test
public void simpleNativeJdbcExtractor() throws SQLException {
SimpleNativeJdbcExtractor extractor = new SimpleNativeJdbcExtractor();
Connection con = mock(Connection.class);
DatabaseMetaData dbmd = mock(DatabaseMetaData.class);
Connection con2 = mock(Connection.class);
given(con.getMetaData()).willReturn(dbmd);
given(dbmd.getConnection()).willReturn(con2);
Connection nativeCon = extractor.getNativeConnection(con);
assertEquals(con2, nativeCon);
Statement stmt = mock(Statement.class);
given(stmt.getConnection()).willReturn(con);
nativeCon = extractor.getNativeConnectionFromStatement(stmt);
assertEquals(con2, nativeCon);
Statement nativeStmt = extractor.getNativeStatement(stmt);
assertEquals(nativeStmt, stmt);
PreparedStatement ps = mock(PreparedStatement.class);
PreparedStatement nativePs = extractor.getNativePreparedStatement(ps);
assertEquals(ps, nativePs);
CallableStatement cs = mock(CallableStatement.class);
ResultSet rs = mock(ResultSet.class);
given(cs.getResultSet()).willReturn(rs);
CallableStatement nativeCs = extractor.getNativeCallableStatement(cs);
assertEquals(cs, nativeCs);
ResultSet nativeRs = extractor.getNativeResultSet(cs.getResultSet());
assertEquals(nativeRs, rs);
}
}

View File

@ -145,7 +145,6 @@ public interface JpaDialect extends PersistenceExceptionTranslator {
* @see org.springframework.jdbc.datasource.ConnectionHandle#getConnection
* @see org.springframework.jdbc.datasource.SimpleConnectionHandle
* @see JpaTransactionManager#setDataSource
* @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor
*/
ConnectionHandle getJdbcConnection(EntityManager entityManager, boolean readOnly)
throws PersistenceException, SQLException;

View File

@ -3222,29 +3222,6 @@ pattern. JTA does not support custom isolation levels!
[[jdbc-NativeJdbcExtractor]]
==== NativeJdbcExtractor
Sometimes you need to access vendor specific JDBC methods that differ from the standard
JDBC API. This can be problematic if you are running in an application server or with a
`DataSource` that wraps the `Connection`, `Statement` and `ResultSet` objects with its
own wrapper objects. To gain access to the native objects you can configure your
`JdbcTemplate` with a `NativeJdbcExtractor`.
The `NativeJdbcExtractor` comes in a variety of flavors to match your execution
environment:
* SimpleNativeJdbcExtractor
* C3P0NativeJdbcExtractor
* JBossNativeJdbcExtractor
* WebLogicNativeJdbcExtractor
* WebSphereNativeJdbcExtractor
Usually the `SimpleNativeJdbcExtractor` is sufficient for unwrapping a `Connection`
object in most environments. See the javadocs for more details.
[[jdbc-advanced-jdbc]]
=== JDBC batch operations
Most JDBC drivers provide improved performance if you batch multiple calls to the same