web-dev-qa-db-ja.com

Apache Commons DBCP接続オブジェクトの問題、スレッド:org.Apache.Tomcat.dbcp.dbcp.PoolingDataSource $ PoolGuardConnectionWrapperのClassCastException

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にキャストできません

ほとんどのサイトやフォーラムでこれに関する解決策を見つけようとしましたが、満足のいく答えや解決策を得ることができませんでした。

27
Prodigy

デフォルトでは、DBCPは「実際の」基礎となるデータベース接続インスタンスへのアクセスを許可しないため、Oracleクラスにアクセスできません。

configuring の場合、設定できます

accessToUnderlyingConnectionAllowed = true

そしてそれは動作します。

デフォルトはfalseです。潜在的な危険な操作であり、プログラムの誤動作により有害なことが行われる可能性があります。 (基礎となる接続を閉じるか、保護された接続が既に閉じられている場合はそれを使用し続けます)注意し、ドライバー固有の拡張機能に直接アクセスする必要がある場合にのみ使用してください

注:元の接続のみを閉じて、基礎となる接続を閉じないでください。

24
Thilo

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 を参照してください

17
Jeff Olson

うーん、私はあなたと同じ解決策に出会った。私はあなたがそれを言及する必要がある2つの位置があると思う。 1.Config接続プールセットaccessToUnderlyingConnectionAllowed = "true"; 2.オープンソースプロジェクトに関係する悪夢。テラブルコンケレーション。この場合、それは

org.Apache.commons.dbcp.DelegatingConnection 

等しくない

org.Apache.Tomcat.dbcp.dbcp.DelegatingConnection

デフォルトのApache common-dbcp.jarでは、フォローするClass.Butを見つけることはできませんが、クラスだけがキーです。だから、どこかでクラスを見つけなければなりません。最後にパッケージ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

それはとても奇妙なことですが、ケースに実際の仕事。

5
Rui Zha

この投稿を見れば、このコードで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がクラスパスにあることを覚えておいてください

5
Leonardo Eloy

私はここでこれを仮定して、アドバイスを探している誰かがこれに対する究極の解決策を知っていることを確認しています:

バンドルされていない永続マネージャを使用することを余儀なくされた場合(古いリポジトリはバンドルされたレイアウトと互換性のない構造を使用しているため)、ここでできることは非常に簡単です:

Jackrabbit Coreのソースをダウンロードします(Jackrabbit Webサイトから入手できます)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を使用してスタンドアロンアプリの機能を使用する場合の問題が修正されました。

    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が必要です。

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

同じ問題に遭遇しました。 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);
1
Sherin Syriac

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();
0
Severus Snape

コンテキスト定義で、既存のxml定義に以下のタグを追加します。

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

0
ibrahimbayer