001/* 002 * Copyright 2002-2015 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.jdbc.support.nativejdbc; 018 019import java.sql.CallableStatement; 020import java.sql.Connection; 021import java.sql.PreparedStatement; 022import java.sql.ResultSet; 023import java.sql.SQLException; 024import java.sql.Statement; 025 026/** 027 * Interface for extracting native JDBC objects from wrapped objects coming from 028 * connection pools. This is necessary to allow for casting to native implementations 029 * like {@code OracleConnection} or {@code OracleResultSet} in application 030 * code, for example to create Blobs or to access vendor-specific features. 031 * 032 * <p>Note: Setting a custom {@code NativeJdbcExtractor} is just necessary 033 * if you intend to cast to database-specific implementations like 034 * {@code OracleConnection} or {@code OracleResultSet}. 035 * Otherwise, any wrapped JDBC object will be fine, with no need for unwrapping. 036 * 037 * <p>Note: To be able to support any pool's strategy of native ResultSet wrapping, 038 * it is advisable to get both the native Statement <i>and</i> the native ResultSet 039 * via this extractor. Some pools just allow to unwrap the Statement, some just to 040 * unwrap the ResultSet - the above strategy will cover both. It is typically 041 * <i>not</i> necessary to unwrap the Connection to retrieve a native ResultSet. 042 * 043 * <p>When working with a simple connection pool that wraps Connections but not 044 * Statements, a {@link SimpleNativeJdbcExtractor} is often sufficient. However, 045 * some pools (like Apache's Commons DBCP) wrap <i>all</i> JDBC objects that they 046 * return: Therefore, you need to use a specific {@code NativeJdbcExtractor} 047 * (like {@link CommonsDbcpNativeJdbcExtractor}) with them. 048 * 049 * <p>{@link org.springframework.jdbc.core.JdbcTemplate} can properly apply a 050 * {@code NativeJdbcExtractor} if specified, unwrapping all JDBC objects 051 * that it creates. Note that this is just necessary if you intend to cast to 052 * native implementations in your data access code. 053 * 054 * <p>{@link org.springframework.jdbc.support.lob.OracleLobHandler}, 055 * the Oracle-specific implementation of Spring's 056 * {@link org.springframework.jdbc.support.lob.LobHandler} interface, requires a 057 * {@code NativeJdbcExtractor} for obtaining the native {@code OracleConnection}. 058 * This is also necessary for other Oracle-specific features that you may want 059 * to leverage in your applications, such as Oracle InterMedia. 060 * 061 * @author Juergen Hoeller 062 * @since 25.08.2003 063 * @see SimpleNativeJdbcExtractor 064 * @see CommonsDbcpNativeJdbcExtractor 065 * @see org.springframework.jdbc.core.JdbcTemplate#setNativeJdbcExtractor 066 * @see org.springframework.jdbc.support.lob.OracleLobHandler#setNativeJdbcExtractor 067 */ 068public interface NativeJdbcExtractor { 069 070 /** 071 * Return whether it is necessary to work on the native Connection to 072 * receive native Statements. 073 * <p>This should be true if the connection pool does not allow to extract 074 * the native JDBC objects from its Statement wrapper but supports a way 075 * to retrieve the native JDBC Connection. This way, applications can 076 * still receive native Statements and ResultSet via working on the 077 * native JDBC Connection. 078 */ 079 boolean isNativeConnectionNecessaryForNativeStatements(); 080 081 /** 082 * Return whether it is necessary to work on the native Connection to 083 * receive native PreparedStatements. 084 * <p>This should be true if the connection pool does not allow to extract 085 * the native JDBC objects from its PreparedStatement wrappers but 086 * supports a way to retrieve the native JDBC Connection. This way, 087 * applications can still receive native Statements and ResultSet via 088 * working on the native JDBC Connection. 089 */ 090 boolean isNativeConnectionNecessaryForNativePreparedStatements(); 091 092 /** 093 * Return whether it is necessary to work on the native Connection to 094 * receive native CallableStatements. 095 * <p>This should be true if the connection pool does not allow to extract 096 * the native JDBC objects from its CallableStatement wrappers but 097 * supports a way to retrieve the native JDBC Connection. This way, 098 * applications can still receive native Statements and ResultSet via 099 * working on the native JDBC Connection. 100 */ 101 boolean isNativeConnectionNecessaryForNativeCallableStatements(); 102 103 /** 104 * Retrieve the underlying native JDBC Connection for the given Connection. 105 * Supposed to return the given Connection if not capable of unwrapping. 106 * @param con the Connection handle, potentially wrapped by a connection pool 107 * @return the underlying native JDBC Connection, if possible; 108 * else, the original Connection 109 * @throws SQLException if thrown by JDBC methods 110 */ 111 Connection getNativeConnection(Connection con) throws SQLException; 112 113 /** 114 * Retrieve the underlying native JDBC Connection for the given Statement. 115 * Supposed to return the {@code Statement.getConnection()} if not 116 * capable of unwrapping. 117 * <p>Having this extra method allows for more efficient unwrapping if data 118 * access code already has a Statement. {@code Statement.getConnection()} 119 * often returns the native JDBC Connection even if the Statement itself 120 * is wrapped by a pool. 121 * @param stmt the Statement handle, potentially wrapped by a connection pool 122 * @return the underlying native JDBC Connection, if possible; 123 * else, the original Connection 124 * @throws SQLException if thrown by JDBC methods 125 * @see java.sql.Statement#getConnection() 126 */ 127 Connection getNativeConnectionFromStatement(Statement stmt) throws SQLException; 128 129 /** 130 * Retrieve the underlying native JDBC Statement for the given Statement. 131 * Supposed to return the given Statement if not capable of unwrapping. 132 * @param stmt the Statement handle, potentially wrapped by a connection pool 133 * @return the underlying native JDBC Statement, if possible; 134 * else, the original Statement 135 * @throws SQLException if thrown by JDBC methods 136 */ 137 Statement getNativeStatement(Statement stmt) throws SQLException; 138 139 /** 140 * Retrieve the underlying native JDBC PreparedStatement for the given statement. 141 * Supposed to return the given PreparedStatement if not capable of unwrapping. 142 * @param ps the PreparedStatement handle, potentially wrapped by a connection pool 143 * @return the underlying native JDBC PreparedStatement, if possible; 144 * else, the original PreparedStatement 145 * @throws SQLException if thrown by JDBC methods 146 */ 147 PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException; 148 149 /** 150 * Retrieve the underlying native JDBC CallableStatement for the given statement. 151 * Supposed to return the given CallableStatement if not capable of unwrapping. 152 * @param cs the CallableStatement handle, potentially wrapped by a connection pool 153 * @return the underlying native JDBC CallableStatement, if possible; 154 * else, the original CallableStatement 155 * @throws SQLException if thrown by JDBC methods 156 */ 157 CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException; 158 159 /** 160 * Retrieve the underlying native JDBC ResultSet for the given statement. 161 * Supposed to return the given ResultSet if not capable of unwrapping. 162 * @param rs the ResultSet handle, potentially wrapped by a connection pool 163 * @return the underlying native JDBC ResultSet, if possible; 164 * else, the original ResultSet 165 * @throws SQLException if thrown by JDBC methods 166 */ 167 ResultSet getNativeResultSet(ResultSet rs) throws SQLException; 168 169}