View Javadoc
1   /*
2    * Copyright 2002-2015 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.jdbc.support.nativejdbc;
18  
19  import java.sql.CallableStatement;
20  import java.sql.Connection;
21  import java.sql.PreparedStatement;
22  import java.sql.ResultSet;
23  import java.sql.SQLException;
24  import java.sql.Statement;
25  
26  /**
27   * Interface for extracting native JDBC objects from wrapped objects coming from
28   * connection pools. This is necessary to allow for casting to native implementations
29   * like {@code OracleConnection} or {@code OracleResultSet} in application
30   * code, for example to create Blobs or to access vendor-specific features.
31   *
32   * <p>Note: Setting a custom {@code NativeJdbcExtractor} is just necessary
33   * if you intend to cast to database-specific implementations like
34   * {@code OracleConnection} or {@code OracleResultSet}.
35   * Otherwise, any wrapped JDBC object will be fine, with no need for unwrapping.
36   *
37   * <p>Note: To be able to support any pool's strategy of native ResultSet wrapping,
38   * it is advisable to get both the native Statement <i>and</i> the native ResultSet
39   * via this extractor. Some pools just allow to unwrap the Statement, some just to
40   * unwrap the ResultSet - the above strategy will cover both. It is typically
41   * <i>not</i> necessary to unwrap the Connection to retrieve a native ResultSet.
42   *
43   * <p>When working with a simple connection pool that wraps Connections but not
44   * Statements, a {@link SimpleNativeJdbcExtractor} is often sufficient. However,
45   * some pools (like Apache's Commons DBCP) wrap <i>all</i> JDBC objects that they
46   * return: Therefore, you need to use a specific {@code NativeJdbcExtractor}
47   * (like {@link CommonsDbcpNativeJdbcExtractor}) with them.
48   *
49   * <p>{@link org.springframework.jdbc.core.JdbcTemplate} can properly apply a
50   * {@code NativeJdbcExtractor} if specified, unwrapping all JDBC objects
51   * that it creates. Note that this is just necessary if you intend to cast to
52   * native implementations in your data access code.
53   *
54   * <p>{@link org.springframework.jdbc.support.lob.OracleLobHandler},
55   * the Oracle-specific implementation of Spring's
56   * {@link org.springframework.jdbc.support.lob.LobHandler} interface, requires a
57   * {@code NativeJdbcExtractor} for obtaining the native {@code OracleConnection}.
58   * This is also necessary for other Oracle-specific features that you may want
59   * to leverage in your applications, such as Oracle InterMedia.
60   *
61   * @author Juergen Hoeller
62   * @since 25.08.2003
63   * @see SimpleNativeJdbcExtractor
64   * @see CommonsDbcpNativeJdbcExtractor
65   * @see org.springframework.jdbc.core.JdbcTemplate#setNativeJdbcExtractor
66   * @see org.springframework.jdbc.support.lob.OracleLobHandler#setNativeJdbcExtractor
67   */
68  public interface NativeJdbcExtractor {
69  
70  	/**
71  	 * Return whether it is necessary to work on the native Connection to
72  	 * receive native Statements.
73  	 * <p>This should be true if the connection pool does not allow to extract
74  	 * the native JDBC objects from its Statement wrapper but supports a way
75  	 * to retrieve the native JDBC Connection. This way, applications can
76  	 * still receive native Statements and ResultSet via working on the
77  	 * native JDBC Connection.
78  	 */
79  	boolean isNativeConnectionNecessaryForNativeStatements();
80  
81  	/**
82  	 * Return whether it is necessary to work on the native Connection to
83  	 * receive native PreparedStatements.
84  	 * <p>This should be true if the connection pool does not allow to extract
85  	 * the native JDBC objects from its PreparedStatement wrappers but
86  	 * supports a way to retrieve the native JDBC Connection. This way,
87  	 * applications can still receive native Statements and ResultSet via
88  	 * working on the native JDBC Connection.
89  	 */
90  	boolean isNativeConnectionNecessaryForNativePreparedStatements();
91  
92  	/**
93  	 * Return whether it is necessary to work on the native Connection to
94  	 * receive native CallableStatements.
95  	 * <p>This should be true if the connection pool does not allow to extract
96  	 * the native JDBC objects from its CallableStatement wrappers but
97  	 * supports a way to retrieve the native JDBC Connection. This way,
98  	 * applications can still receive native Statements and ResultSet via
99  	 * 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 }