Apache Commons DBCP连接对象问题,org.apache.tomcat.dbcp.dbcp.PoolingDataSource中的Thread:ClassCastException $ PoolGuardConnectionWrapper

我正在使用Apache Commons DBCP( commons-dbcp.jar )连接池。

一旦我从池中获得连接,它就被包装在类org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper

我的要求是将一个字符串数组传递给Oracle中的pl / sql存储过程。

以下是我在以下代码片段中所做的事情:

 Connection dbConn = ConnectionManager.ds.getConnection(); //The above statement returns me an connection wrapped in the class //org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper. org.apache.commons.dbcp.DelegatingConnection del = new org.apache.commons.dbcp.DelegatingConnection(dbConn.getConnection()); con = del.getInnermostDelegate(); cs = con.prepareCall("call SP_NAME(?,?,?,?)"); oracle.sql.ArrayDescriptor arDesc= oracle.sql.ArrayDescriptor.createDescriptor("ARRAY_NAME", (OracleConnection) con); CallableStatement c_stmt = conn.prepareCall("begin update_message_ids_ota (:x); end;" ); c_stmt.setArray( 1, array_to_pass ); c_stmt.execute(); 

执行上面的代码时,我得到以下exception:

java.lang.ClassCastException:org.apache.commons.dbcp.PoolingDataSource $ PoolGuardConnectionWrapper无法在oracle.sql.ArrayDescriptor.createDescriptor中强制转换为oracle.jdbc.OracleConnection

我试图在几乎所有的网站和论坛中找到解决方案,但无法得到满意的答案或解决方案。

默认情况下,DBCP不允许访问“真正的”底层数据库连接实例,因此无法访问Oracle类。

配置池时,您可以进行设置

 accessToUnderlyingConnectionAllowed = true 

然后它的工作原理。

默认是假的,这是一个潜在的危险操作,行为不端的程序可以做有害的事情。 (在保护连接已经关闭时关闭底层或继续使用它)小心并且仅在需要直接访问驱动程序特定扩展时使用

注意:不要关闭底层连接,只关闭原始连接。

如果您使用的是Java 6兼容的JDBC连接,则可以使用如下代码:

 OracleConnection oracleConnection = null; try { if (connection.isWrapperFor(OracleConnection.class)) { oracleConnection = connection.unwrap(OracleConnection.class); } } catch (SQLException ex) { // do something } return oracleConnection; 

从现在开始,使用oracleConnection而不是原始connection

请参阅http://docs.oracle.com/javase/6/docs/api/java/sql/Wrapper.html

看到这篇文章,我可以使用以下代码获取OracleConnection:

 DataSource ds1 = // get the org.apache.commons.dbcp.PoolingDataSource org.apache.tomcat.dbcp.dbcp.DelegatingConnection del = new org.apache.tomcat.dbcp.dbcp.DelegatingConnection(cds1.getConnection()); OracleConnection con = (OracleConnection) del.getInnermostDelegate(); 

记住commons-dbcp-1.4.jar neet是在类路径中

嗯,我遇到了和你一样的解决方案。我认为有两个位置需要你提一下。 1.Config连接池设置accessToUnderlyingConnectionAllowed =“true”; 2.关于开源项目的噩梦。 可怕的概念。 在这种情况下,就是这样

 org.apache.commons.dbcp.DelegatingConnection 

不等于

 org.apache.tomcat.dbcp.dbcp.DelegatingConnection 

而在默认的apache common-dbcp.jar中,你永远不会找到跟随Class.But只是类是关键。 所以,我们必须在某个地方找到Class。 我最终找到了包tomcat-dbcp .jar。 你可以从http://www.docjar.com/获得它

 import org.apache.tomcat.dbcp.dbcp.DelegatingConnection 

,你可以强制转换你的dbConn并获得底层连接

 oracle.jdbc.driver.OracleConnection delConn = (oracle.jdbc.driver.OracleConnection) ((org.apache.tomcat.dbcp.dbcp.DelegatingConnection)c_stmt.getConnection()).getDelegate(); 

然后我们可以使用delConn来获取ArrayDescriptor记住一件事,在那里,我们不需要

 org.apache.commons.dbcp.DelegatingConnection Class 

这是一件非常奇怪的事情,但对案件的真实工作。

我在这里提出这个问题,以确保寻找建议的其他人知道最终的解决方案:

如果您被迫使用非捆绑版本的持久性管理器(因为旧的存储库仍然使用与捆绑布局不兼容的结构),在这里您可以做的,解决方案非常简单:

下载Jackrabbit Core的源代码(您可以从Jackrabbit网站获取它们)打开OraclePersistenceManager类并找到以下代码行:

 Object blob = createTemporary.invoke(null, new Object[]{con, Boolean.FALSE, durationSessionConstant}); 

(第377行 – 也可以查看StackTrace以供参考)

ConnectionFactory包含一个静态方法,允许解开正是您所需的连接:

 Object blob = createTemporary.invoke(null, new Object[]{org.apache.jackrabbit.core.util.db.ConnectionFactory .unwrap(con), Boolean.FALSE, durationSessionConstant}); 

你需要Maven 2+来编译源代码,我这样做并且没有依赖性问题,请注意我编译了Jackrabbit的2.2.10版本。

我还确保记录针对Jackrabbit 2.2.11的错误(当前版本仍有问题): https : //issues.apache.org/jira/browse/JCR-3262

希望这可以帮助!

我们在调用oracle存储过程中使用数组,并使用oracle专有api来构建数组。 当使用commons-dbcp的独立应用程序中的function时,这个小小的检查为我们解决了问题。

  if (conn instanceof org.apache.commons.dbcp.DelegatingConnection) { log.debug("detected apache commons dbcp datasource"); conn = ((org.apache.commons.dbcp.DelegatingConnection) conn).getInnermostDelegate(); } 

但是,您需要在classpath / dependecies中使用commons-dbcp。

   commons-dbcp commons-dbcp 1.4 provided  

我遇到过同样的问题。 我们使用spring,它有一个名为NativeJdbcExtractor的类。 它有许多实现,以下一个适用于TomCat。 Websphere,Weblogic应用服务器有特定的实现。

  

在DAO中,您可以注入bean并使用以下方法

 protected NativeJdbcExtractor jdbcExtractor; Connection conn=jdbcExtractor.getNativeConnection(oracleConnection); 

在上下文定义中,将以下标记添加到现有的xml定义中。

 factory="oracle.jdbc.pool.OracleDataSourceFactory scope="Shareable" type="oracle.jdbc.pool.OracleDataSource" 

对于其他任何人来说, getDelegate()getInnermostDelegate()都在我的代码中返回NULL 。 但是,从调试器中我发现了OracleConnection,如下所示。 我们在整个应用程序中使用Spring JdbcTemplate,它注入了数据源。 我们在spring-jdbc-4.1.5.RELEASE.jar和ojdbc6.jar上。

 Connection conn = getJdbcTemplate().getDataSource().getConnection(); OracleConnection oracleConnection = ( OracleConnection ) conn.getMetaData().getConnection(); 

我正在使用tomcat 8.5.8并且正面临着这个问题。
以下解决方案就像魅力一样。


代码:

 Delegating Connection delegate_conn = new Delegating Connection(connection) conn = delegate_conn.getInnermostDelegate(); oracle.sql.ArrayDescriptor desc = oracle.sql.ArrayDescriptor.createDescriptor("TABLE_VIEW", conn); 

解决方案:

tomcat-dbcp 8.5.8添加依赖项,并在tomcat的lib文件夹中添加相同的jar。
看起来tomcat对于从7.0开始的不同版本有不同的jar(参考: https : //mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp )。

希望它可以帮到某人。