diff --git a/pom.xml b/pom.xml index c1cfcc86ce..067aa03609 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,6 @@ - org.apache.maven.plugins maven-compiler-plugin @@ -71,7 +70,6 @@ - org.apache.maven.plugins maven-surefire-plugin diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledCallableStatement.java b/src/main/java/com/alibaba/druid/pool/DruidPooledCallableStatement.java index 4b32049cda..16d8902d01 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledCallableStatement.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledCallableStatement.java @@ -30,6 +30,8 @@ import java.sql.SQLFeatureNotSupportedException; import java.sql.SQLXML; import java.util.Calendar; +import com.alibaba.druid.proxy.jdbc.CallableStatementProxy; + /** * @author wenshao */ @@ -1054,4 +1056,15 @@ public class DruidPooledCallableStatement extends DruidPooledPreparedStatement i throw new SQLFeatureNotSupportedException(); } + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == CallableStatement.class) { + if (stmt instanceof CallableStatementProxy) { + return stmt.unwrap(iface); + } + return (T) stmt; + } + + return super.unwrap(iface); + } } diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java index e5e1641c57..6b549f9af3 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java @@ -43,6 +43,7 @@ import com.alibaba.druid.logging.Log; import com.alibaba.druid.logging.LogFactory; import com.alibaba.druid.pool.DruidPooledPreparedStatement.PreparedStatementKey; import com.alibaba.druid.pool.PreparedStatementPool.MethodType; +import com.alibaba.druid.proxy.jdbc.ConnectionProxy; import com.alibaba.druid.util.TransactionInfo; /** @@ -540,6 +541,14 @@ public class DruidPooledConnection implements javax.sql.PooledConnection, Connec if (iface == null) { return null; } + + if (iface == Connection.class) { + if (conn instanceof ConnectionProxy) { + return conn.unwrap(iface); + } + + return (T) conn; + } if (iface.isInstance(this)) { return (T) this; diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledPreparedStatement.java b/src/main/java/com/alibaba/druid/pool/DruidPooledPreparedStatement.java index 4f93330fff..e90d23a0c9 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledPreparedStatement.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledPreparedStatement.java @@ -38,6 +38,7 @@ import java.util.Arrays; import java.util.Calendar; import com.alibaba.druid.pool.PreparedStatementPool.MethodType; +import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy; import com.alibaba.druid.util.OracleUtils; /** @@ -987,4 +988,16 @@ public class DruidPooledPreparedStatement extends DruidPooledStatement implement } } + + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == PreparedStatement.class) { + if (stmt instanceof PreparedStatementProxy) { + return stmt.unwrap(iface); + } + return (T) stmt; + } + + return super.unwrap(iface); + } } diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledResultSet.java b/src/main/java/com/alibaba/druid/pool/DruidPooledResultSet.java index 1dc2491ee2..8569175048 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledResultSet.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledResultSet.java @@ -33,6 +33,8 @@ import java.sql.SQLXML; import java.sql.Statement; import java.util.Calendar; +import com.alibaba.druid.proxy.jdbc.ResultSetProxy; + /** * @author wenshao */ @@ -1766,4 +1768,17 @@ public final class DruidPooledResultSet extends PoolableWrapper implements Resul public T getObject(String columnLabel, Class type) throws SQLException { throw new SQLFeatureNotSupportedException(); } + + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == ResultSet.class) { + if (rs instanceof ResultSetProxy) { + return rs.unwrap(iface); + } + + return (T) rs; + } + + return super.unwrap(iface); + } } diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java b/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java index a50ebe7adf..8820e5fae2 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledStatement.java @@ -25,6 +25,7 @@ import java.util.List; import com.alibaba.druid.logging.Log; import com.alibaba.druid.logging.LogFactory; +import com.alibaba.druid.proxy.jdbc.StatementProxy; /** * @author wenshao @@ -578,4 +579,16 @@ public class DruidPooledStatement extends PoolableWrapper implements Statement { public boolean isCloseOnCompletion() throws SQLException { return false; } + + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == Statement.class) { + if (stmt instanceof StatementProxy) { + return stmt.unwrap(iface); + } + return (T) stmt; + } + + return super.unwrap(iface); + } } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/CallableStatementProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/CallableStatementProxyImpl.java index 36e174981e..a381d3f950 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/CallableStatementProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/CallableStatementProxyImpl.java @@ -23,6 +23,7 @@ import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.NClob; +import java.sql.PreparedStatement; import java.sql.Ref; import java.sql.RowId; import java.sql.SQLException; @@ -609,4 +610,12 @@ public class CallableStatementProxyImpl extends PreparedStatementProxyImpl imple throw new SQLFeatureNotSupportedException(); } + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == PreparedStatement.class) { + return (T) statement; + } + + return super.unwrap(iface); + } } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/ConnectionProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/ConnectionProxyImpl.java index 1b89dfbe84..2e9ea7a507 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/ConnectionProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/ConnectionProxyImpl.java @@ -341,4 +341,12 @@ public class ConnectionProxyImpl extends WrapperProxyImpl implements ConnectionP throw new SQLFeatureNotSupportedException(); } + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == Connection.class) { + return (T) connection; + } + + return super.unwrap(iface); + } } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java index 748794e38a..46759be9b0 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java @@ -342,4 +342,13 @@ public class PreparedStatementProxyImpl extends StatementProxyImpl implements Pr public String getLastExecuteSql() { return this.sql; } + + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == PreparedStatement.class) { + return (T) statement; + } + + return super.unwrap(iface); + } } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java index 79bd97fd08..f48f438885 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java @@ -1050,4 +1050,12 @@ public class ResultSetProxyImpl extends WrapperProxyImpl implements ResultSetPro throw new SQLFeatureNotSupportedException(); } + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == ResultSet.class) { + return (T) resultSet; + } + + return super.unwrap(iface); + } } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java index 61f61f9da9..47b57510b3 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java @@ -314,4 +314,13 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro public boolean isCloseOnCompletion() throws SQLException { throw new SQLFeatureNotSupportedException(); } + + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == Statement.class) { + return (T) statement; + } + + return super.unwrap(iface); + } } diff --git a/src/main/java/com/alibaba/druid/spring/DruidJdbcExtractor.java b/src/main/java/com/alibaba/druid/spring/DruidJdbcExtractor.java index b56a67a789..35b61d63ca 100644 --- a/src/main/java/com/alibaba/druid/spring/DruidJdbcExtractor.java +++ b/src/main/java/com/alibaba/druid/spring/DruidJdbcExtractor.java @@ -1,111 +1,7 @@ package com.alibaba.druid.spring; -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.jdbc.support.nativejdbc.Jdbc4NativeJdbcExtractor; -import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor; - -import com.alibaba.druid.pool.DruidPooledCallableStatement; -import com.alibaba.druid.pool.DruidPooledConnection; -import com.alibaba.druid.pool.DruidPooledPreparedStatement; -import com.alibaba.druid.pool.DruidPooledResultSet; -import com.alibaba.druid.pool.DruidPooledStatement; -import com.alibaba.druid.proxy.jdbc.CallableStatementProxy; -import com.alibaba.druid.proxy.jdbc.ConnectionProxy; -import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy; -import com.alibaba.druid.proxy.jdbc.ResultSetProxy; -import com.alibaba.druid.proxy.jdbc.StatementProxy; - - -public class DruidJdbcExtractor implements NativeJdbcExtractor { - - @Override - public boolean isNativeConnectionNecessaryForNativeStatements() { - return true; - } - - @Override - public boolean isNativeConnectionNecessaryForNativePreparedStatements() { - return true; - } - - @Override - public boolean isNativeConnectionNecessaryForNativeCallableStatements() { - return true; - } - - @Override - public Connection getNativeConnection(Connection conn) throws SQLException { - if (conn instanceof DruidPooledConnection) { - conn = ((DruidPooledConnection) conn).getConnection(); - } - - if (conn instanceof ConnectionProxy) { - conn = ((ConnectionProxy) conn).getConnectionRaw(); - } - - return conn; - } - - @Override - public Connection getNativeConnectionFromStatement(Statement stmt) throws SQLException { - return getNativeConnection(stmt.getConnection()); - } - - @Override - public Statement getNativeStatement(Statement stmt) throws SQLException { - if (stmt instanceof DruidPooledStatement) { - stmt = ((DruidPooledStatement) stmt).getStatement(); - } - - if (stmt instanceof StatementProxy) { - stmt = ((StatementProxy) stmt).getStatementRaw(); - } - - return stmt; - } - - @Override - public PreparedStatement getNativePreparedStatement(PreparedStatement stmt) throws SQLException { - if (stmt instanceof DruidPooledPreparedStatement) { - stmt = ((DruidPooledPreparedStatement) stmt).getRawPreparedStatement(); - } - - if (stmt instanceof PreparedStatementProxy) { - stmt = ((PreparedStatementProxy) stmt).getRawPreparedStatement(); - } - - return stmt; - } - - @Override - public CallableStatement getNativeCallableStatement(CallableStatement stmt) throws SQLException { - if (stmt instanceof DruidPooledCallableStatement) { - stmt = ((DruidPooledCallableStatement) stmt).getCallableStatementRaw(); - } - - if (stmt instanceof CallableStatementProxy) { - stmt = ((CallableStatementProxy) stmt).getRawCallableStatement(); - } - - return stmt; - } - - @Override - public ResultSet getNativeResultSet(ResultSet rs) throws SQLException { - if (rs instanceof DruidPooledResultSet) { - rs = ((DruidPooledResultSet) rs).getRawResultSet(); - } - - if (rs instanceof ResultSetProxy) { - rs = ((ResultSetProxy) rs).getResultSetRaw(); - } - - return rs; - } +public class DruidJdbcExtractor extends Jdbc4NativeJdbcExtractor { } diff --git a/src/main/java/com/alibaba/druid/util/OracleUtils.java b/src/main/java/com/alibaba/druid/util/OracleUtils.java index 981d133f75..d0cd5b70a7 100644 --- a/src/main/java/com/alibaba/druid/util/OracleUtils.java +++ b/src/main/java/com/alibaba/druid/util/OracleUtils.java @@ -88,6 +88,7 @@ public class OracleUtils { oracleConn.setStatementCacheSize(size); } + @SuppressWarnings("deprecation") public static int pingDatabase(Connection conn) throws SQLException { OracleConnection oracleConn = unwrap(conn); return oracleConn.pingDatabase(1000); diff --git a/src/test/java/com/alibaba/druid/bvt/spring/DruidJdbcExtractorTest.java b/src/test/java/com/alibaba/druid/bvt/spring/DruidJdbcExtractorTest.java index baac25c339..05216f7bc7 100644 --- a/src/test/java/com/alibaba/druid/bvt/spring/DruidJdbcExtractorTest.java +++ b/src/test/java/com/alibaba/druid/bvt/spring/DruidJdbcExtractorTest.java @@ -7,6 +7,9 @@ import java.sql.Statement; import junit.framework.Assert; import junit.framework.TestCase; +import org.springframework.jdbc.support.nativejdbc.Jdbc4NativeJdbcExtractor; + +import com.alibaba.druid.mock.MockCallableStatement; import com.alibaba.druid.mock.MockConnection; import com.alibaba.druid.mock.MockPreparedStatement; import com.alibaba.druid.mock.MockStatement; @@ -37,6 +40,12 @@ public class DruidJdbcExtractorTest extends TestCase { Assert.assertEquals(true, extractor.getNativePreparedStatement(preStmt) instanceof MockPreparedStatement); preStmt.close(); + PreparedStatement callStmt = conn.prepareCall("select 1"); + Assert.assertEquals(true, extractor.getNativeConnectionFromStatement(callStmt) instanceof MockConnection); + Assert.assertEquals(true, extractor.getNativeStatement(callStmt) instanceof MockCallableStatement); + Assert.assertEquals(true, extractor.getNativePreparedStatement(callStmt) instanceof MockCallableStatement); + callStmt.close(); + conn.close(); } finally { dataSource.close(); @@ -47,7 +56,7 @@ public class DruidJdbcExtractorTest extends TestCase { DruidDataSource dataSource = new DruidDataSource(); try { - DruidJdbcExtractor extractor = new DruidJdbcExtractor(); + Jdbc4NativeJdbcExtractor extractor = new Jdbc4NativeJdbcExtractor(); dataSource.setUrl("jdbc:mock:xx1"); dataSource.setFilters("stat"); @@ -66,6 +75,12 @@ public class DruidJdbcExtractorTest extends TestCase { Assert.assertEquals(true, extractor.getNativePreparedStatement(preStmt) instanceof MockPreparedStatement); preStmt.close(); + PreparedStatement callStmt = conn.prepareCall("select 1"); + Assert.assertEquals(true, extractor.getNativeConnectionFromStatement(callStmt) instanceof MockConnection); + Assert.assertEquals(true, extractor.getNativeStatement(callStmt) instanceof MockCallableStatement); + Assert.assertEquals(true, extractor.getNativePreparedStatement(callStmt) instanceof MockCallableStatement); + callStmt.close(); + conn.close(); } finally { dataSource.close(); diff --git a/src/test/java/com/alibaba/druid/bvt/spring/Jdbc4ExtractorTest.java b/src/test/java/com/alibaba/druid/bvt/spring/Jdbc4ExtractorTest.java new file mode 100644 index 0000000000..2db0d9be63 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/spring/Jdbc4ExtractorTest.java @@ -0,0 +1,99 @@ +package com.alibaba.druid.bvt.spring; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.springframework.jdbc.support.nativejdbc.Jdbc4NativeJdbcExtractor; + +import com.alibaba.druid.mock.MockCallableStatement; +import com.alibaba.druid.mock.MockConnection; +import com.alibaba.druid.mock.MockPreparedStatement; +import com.alibaba.druid.mock.MockResultSet; +import com.alibaba.druid.mock.MockStatement; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.spring.DruidJdbcExtractor; + +public class Jdbc4ExtractorTest extends TestCase { + + public void test_spring() throws Exception { + DruidDataSource dataSource = new DruidDataSource(); + + try { + Jdbc4NativeJdbcExtractor extractor = new Jdbc4NativeJdbcExtractor(); + + dataSource.setUrl("jdbc:mock:xx1"); + Connection conn = dataSource.getConnection(); + Assert.assertEquals(true, extractor.getNativeConnection(conn) instanceof MockConnection); + + Statement stmt = conn.createStatement(); + Assert.assertEquals(true, extractor.getNativeConnectionFromStatement(stmt) instanceof MockConnection); + Assert.assertEquals(true, extractor.getNativeStatement(stmt) instanceof MockStatement); + + stmt.close(); + + PreparedStatement preStmt = conn.prepareStatement("select 1"); + Assert.assertEquals(true, extractor.getNativeConnectionFromStatement(preStmt) instanceof MockConnection); + Assert.assertEquals(true, extractor.getNativeStatement(preStmt) instanceof MockPreparedStatement); + Assert.assertEquals(true, extractor.getNativePreparedStatement(preStmt) instanceof MockPreparedStatement); + ResultSet rs = preStmt.executeQuery(); + Assert.assertEquals(true, extractor.getNativeResultSet(rs) instanceof MockResultSet); + rs.close(); + + preStmt.close(); + + PreparedStatement callStmt = conn.prepareCall("select 1"); + Assert.assertEquals(true, extractor.getNativeConnectionFromStatement(callStmt) instanceof MockConnection); + Assert.assertEquals(true, extractor.getNativeStatement(callStmt) instanceof MockCallableStatement); + Assert.assertEquals(true, extractor.getNativePreparedStatement(callStmt) instanceof MockCallableStatement); + callStmt.close(); + + conn.close(); + } finally { + dataSource.close(); + } + } + + public void test_spring_filter() throws Exception { + DruidDataSource dataSource = new DruidDataSource(); + + try { + DruidJdbcExtractor extractor = new DruidJdbcExtractor(); + + dataSource.setUrl("jdbc:mock:xx1"); + dataSource.setFilters("stat"); + Connection conn = dataSource.getConnection(); + Assert.assertEquals(true, extractor.getNativeConnection(conn) instanceof MockConnection); + + Statement stmt = conn.createStatement(); + Assert.assertEquals(true, extractor.getNativeConnectionFromStatement(stmt) instanceof MockConnection); + Assert.assertEquals(true, extractor.getNativeStatement(stmt) instanceof MockStatement); + + stmt.close(); + + PreparedStatement preStmt = conn.prepareStatement("select 1"); + Assert.assertEquals(true, extractor.getNativeConnectionFromStatement(preStmt) instanceof MockConnection); + Assert.assertEquals(true, extractor.getNativeStatement(preStmt) instanceof MockPreparedStatement); + Assert.assertEquals(true, extractor.getNativePreparedStatement(preStmt) instanceof MockPreparedStatement); + ResultSet rs = preStmt.executeQuery(); + Assert.assertEquals(true, extractor.getNativeResultSet(rs) instanceof MockResultSet); + rs.close(); + + preStmt.close(); + + PreparedStatement callStmt = conn.prepareCall("select 1"); + Assert.assertEquals(true, extractor.getNativeConnectionFromStatement(callStmt) instanceof MockConnection); + Assert.assertEquals(true, extractor.getNativeStatement(callStmt) instanceof MockCallableStatement); + Assert.assertEquals(true, extractor.getNativePreparedStatement(callStmt) instanceof MockCallableStatement); + callStmt.close(); + + conn.close(); + } finally { + dataSource.close(); + } + } +}