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}