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

发布于 2024-11-17 04:52:39 字数 1228 浏览 3 评论 0原文

我正在使用 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();

在执行上述代码时,出现以下异常:

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

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

I am using Apache Commons DBCP (commons-dbcp.jar) Connection pool.

Once I obtained a connection from the pool it is wrapped in the
class org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.

My requirement is to pass an array of Strings to pl/sql stored procedure in Oracle.

Here is what I am doing in the following code snippet:

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();

On executing the above code, I get the following exception:

java.lang.ClassCastException: org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to oracle.jdbc.OracleConnection
at oracle.sql.ArrayDescriptor.createDescriptor

I tried to find out solution over this going throughout almost of the sites and forums, but couldn't get the satisfied answer or solution on the same.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

赏烟花じ飞满天 2024-11-24 04:52:39

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

配置池时,您可以设置

accessToUnderlyingConnectionAllowed = true

然后它就可以工作。

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

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

By default, DBCP does not allow access to the "real" underlying database connection instance, so you cannot get to the Oracle class.

When configuring the pool, you can set

accessToUnderlyingConnectionAllowed = true

and then it works.

Default is false, it is a potential dangerous operation and misbehaving programs can do harmful things. (closing the underlying or continue using it when the guarded connection is already closed) Be careful and only use when you need direct access to driver specific extensions

NOTE: Do not close the underlying connection, only the original one.

满地尘埃落定 2024-11-24 04:52:39

如果您使用的是 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

If you are using a Java 6 compliant JDBC Connection, you can use code like the following:

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

From this point on, use the oracleConnection instead of the original connection.

See http://docs.oracle.com/javase/6/docs/api/java/sql/Wrapper.html

醉梦枕江山 2024-11-24 04:52:39

看到这篇文章我可以使用以下代码获取 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 位于类路径中

Seen this post i can get the OracleConnection with this code:

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();

remember the commons-dbcp-1.4.jar neet to be in the class path

情独悲 2024-11-24 04:52:39

嗯,我遇到了和你一样的解决方案。我认为有两个位置需要你提到。
1.配置连接池设置accessToUnderlyingConnectionAllowed = "true" ;
2.开源项目的噩梦。伟大的专注。在这种情况下,即
is

org.apache.commons.dbcp.DelegatingConnection 

不等于

org.apache.tomcat.dbcp.dbcp.DelegatingConnection

while 在默认的 apache common-dbcp.jar 中,你永远找不到下面的类。但类才是关键。所以,我们必须在某个地方找到这个类。我最终找到了包 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

这是一件如此奇怪的事情,而是真正的工作。

Hmmm,I have meet the same solution like you.I think there a two position need you mention it.
1.Config Connection pool set accessToUnderlyingConnectionAllowed = "true" ;
2.The nightmare concerned to open source project. The terrable conceration. In this case,that
is

org.apache.commons.dbcp.DelegatingConnection 

is not equal to

org.apache.tomcat.dbcp.dbcp.DelegatingConnection

while in default apache common-dbcp.jar,you will never find the follow Class.But just the class is the key. So,we must find the Class in somewhere. I final find the package tomcat-dbcp.jar . You can get it from http://www.docjar.com/
After

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

,you can force cast you dbConn and get the Underlying Connection

oracle.jdbc.driver.OracleConnection delConn = 

(oracle.jdbc.driver.OracleConnection) 

((org.apache.tomcat.dbcp.dbcp.DelegatingConnection)c_stmt.getConnection()).getDelegate();

Then we can use delConn to get the ArrayDescriptor
Remember one thing,in there,we do not need the

org.apache.commons.dbcp.DelegatingConnection Class

It's a so strange thing,but real work to the case.

野生奥特曼 2024-11-24 04:52:39

我在这里提出这一点是为了确保其他寻求建议的人知道最终的解决方案:

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

下载 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

希望这有帮助!

I'm positing this here to make sure anyone else looking for advice knows about the ultimate solution to this:

If you're forced to use the non bundled version of the persistence manager (because an old repository still uses that structure which is incompatible with the bundled layout), here what you can do, the solution is quite simple:

Download the sources for Jackrabbit Core (you can get them from the Jackrabbit website)
Open the OraclePersistenceManager class and find the following line of code:

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

(Around line 377 - can also check the StackTrace for reference)

ConnectionFactory contains a static method that allows to unwrap a connection which is exactly what you need:

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

You will need Maven 2+ in order to compile the sources, I did that and had no dependency problems, note that I compiled version 2.2.10 of Jackrabbit.

I also made sure to log a bug against Jackrabbit 2.2.11 (current release which still has the issue):
https://issues.apache.org/jira/browse/JCR-3262

Hope this helps!

饭团 2024-11-24 04:52:39

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

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

不过,您将需要在类路径/依赖项中使用 commons-dbcp。

    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
        <scope>provided</scope>
    </dependency>

We use arrays in our calls to oracle stored procs and use oracle proprietary api to build arrays. This little check fixed the issue for us when using the functionality from stand alone apps using commons-dbcp.

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

You will need commons-dbcp in the classpath/dependecies though.

    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
        <scope>provided</scope>
    </dependency>
我的奇迹 2024-11-24 04:52:39

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

<bean id="jdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"></bean>

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

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

I had encountered the same issue. We were using spring and it has a class called
NativeJdbcExtractor. It has many implementations and the following one works for TomCat. There are specific implementations for Websphere,Weblogic app servers.

<bean id="jdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"></bean>

In your DAO you can inject the bean and use the following method

protected NativeJdbcExtractor jdbcExtractor;
Connection conn=jdbcExtractor.getNativeConnection(oracleConnection);
蹲在坟头点根烟 2024-11-24 04:52:39

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

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

in your context definition add below tags to your existing xml definition.

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

.

生生不灭 2024-11-24 04:52:39

对于其他人来说,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();

For anyone else looking, getDelegate() and getInnermostDelegate() both return NULL in my code. However, from the debugger I found the OracleConnection as below. We use Spring JdbcTemplate throughout the application, which has the data source injected. We're on spring-jdbc-4.1.5.RELEASE.jar and ojdbc6.jar.

Connection conn = getJdbcTemplate().getDataSource().getConnection();

OracleConnection oracleConnection = ( OracleConnection ) conn.getMetaData().getConnection();
我只土不豪 2024-11-24 04:52:39

我正在使用 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。
似乎从7.0开始,tomcat对于不同版本有不同的jar(参考:https:// mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp)。

希望它能帮助某人。

I am working with tomcat 8.5.8 and was facing this issue.
The below solution worked like charm.


The Code:

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

The Solution:

Adding dependency for tomcat-dbcp 8.5.8
and add the same jar in lib folder of tomcat.
Seems tomcat has different jars for different versions starting from 7.0 (reference: https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp).

Hope it helps someone.

瑾兮 2024-11-24 04:52:39

我正在使用 java7 & ojdbc7.jar & Tomcat 8。

在转换 ((OracleConnection)connection).createARRAY 时,我在 tomcat 中遇到了同样的问题

在搜索了大量解决方案和论坛后,最后对我来说有效的解决方案是,

Connection connection = datasource.getConnection();
CallableStatement cs = connection.prepareCall("{ CALL PKG.PROCEDURE(?)}");

if(cs.getConnection().isWrapperFor(OracleConnection.class)) {
  OracleConnection orConn = cs.getConnection().unwrap(OracleConnection.class);
  orConn.createARRAY ..// is working perfectly.

}

如果您这样做 connection.isWrapperFor(OracleConnection.class )你会得到错误的结果。你需要使用cs.getConnection。

可能会帮助某人。

I'm using java7 & ojdbc7.jar & Tomcat 8.

I had the same issue in tomcat while converting ((OracleConnection)connection).createARRAY

After searching for lot of solutions and forums, finally the worked solution for me is,

Connection connection = datasource.getConnection();
CallableStatement cs = connection.prepareCall("{ CALL PKG.PROCEDURE(?)}");

if(cs.getConnection().isWrapperFor(OracleConnection.class)) {
  OracleConnection orConn = cs.getConnection().unwrap(OracleConnection.class);
  orConn.createARRAY ..// is working perfectly.

}

If you did connection.isWrapperFor(OracleConnection.class) you will get false. you need to use cs.getConnection.

Might help someone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文