28

我正在使用 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.sql.ArrayDescriptor.createDescriptor 中转换为 oracle.jdbc.OracleConnection

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

4

11 回答 11

25

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

配置池时,可以设置

accessToUnderlyingConnectionAllowed = true

然后它就起作用了。

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

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

于 2011-06-27T06:59:25.897 回答
18

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

于 2013-01-14T21:48:27.970 回答
6

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

于 2012-04-20T00:20:00.490 回答
5

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

org.apache.commons.dbcp.DelegatingConnection 

不等于

org.apache.tomcat.dbcp.dbcp.DelegatingConnection

而在默认的 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

这是一件很奇怪的事情,但对这个案子来说是真正的工作。

于 2012-04-06T11:47:43.860 回答
2

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

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

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

希望这可以帮助!

于 2012-03-16T17:16:10.733 回答
1

我遇到了同样的问题。我们使用的是 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);
于 2013-10-16T04:14:06.227 回答
1

我们在调用 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>
于 2012-05-25T07:44:01.017 回答
0

对于其他人来说,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();
于 2016-02-19T19:14:05.403 回答
0

我正在使用 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的lib文件夹中添加依赖tomcat-dbcp 8.5.8 并添加相同的jar。
似乎tomcat从7.0开始有不同版本的不同jar(参考:https ://mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp )。

希望它可以帮助某人。

于 2016-12-19T10:25:19.737 回答
0

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

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

.

于 2015-07-30T11:07:16.667 回答
0

我正在使用 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。

可能会帮助某人。

于 2019-11-06T14:54:26.367 回答