Проблема объекта подключения DBCP Apache Commons, Поток: ClassCastException в org.apache.tomcat.dbcp.dbcp.PoolingDataSource $ PoolGuardConnectionWrapper - PullRequest
26 голосов
/ 27 июня 2011

Я использую пул соединений Apache Commons DBCP (commons-dbcp.jar).

После получения соединения из пула оно помещается в класс org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.

Моё требованиепередать массив строк в хранимую процедуру pl / sql в Oracle.

Вот что я делаю в следующем фрагменте кода:

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.orre5

Я пытался найти решение этой проблемы почти на всех сайтах и ​​форумах, но не смог получить удовлетворенный ответ или решение по этому поводу.

Ответы [ 10 ]

23 голосов
/ 27 июня 2011

По умолчанию DBCP не разрешает доступ к «реальному» базовому экземпляру соединения с базой данных, поэтому вы не можете получить доступ к классу Oracle.

Когда настраивает пул, вы можете установить

accessToUnderlyingConnectionAllowed = true

и тогда это работает.

По умолчанию установлено значение false, это потенциально опасная операция, и неправильно работающие программы могут совершать опасные действия. (закрытие базового или продолжение его использования, когда защищенное соединение уже закрыто) Будьте осторожны и используйте его только тогда, когда вам нужен прямой доступ к конкретным расширениям драйвера

ПРИМЕЧАНИЕ. Не закрывайте основное соединение, только оригинальное.

16 голосов
/ 15 января 2013

Если вы используете JDBC-соединение, совместимое с Java 6, вы можете использовать код, подобный следующему:

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

5 голосов
/ 20 апреля 2012

Посмотрев этот пост, я могу получить 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 находится в пути к классам

4 голосов
/ 06 апреля 2012

Хммм , Я встречал то же решение, что и вы. Думаю, вам нужно упомянуть две позиции. 1.Config Пул соединений set 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

Это так странно, но настоящая работа для дела.

2 голосов
/ 16 марта 2012

Я предлагаю это здесь, чтобы убедиться, что кто-то еще, ищущий совета, знает об окончательном решении этого вопроса:

Если вы вынуждены использовать не связанную версию диспетчера персистентности (поскольку старый репозиторий по-прежнему использует ту структуру, которая несовместима с компоновкой в ​​комплекте), то здесь вы можете сделать довольно простое решение:

Скачать исходники для 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+, чтобы скомпилировать исходники, я сделал это и у меня не было проблем с зависимостями, обратите внимание, что я скомпилировал версию 2.2.10 Jackrabbit.

Я также удостоверился, что зарегистрировал ошибку против Jackrabbit 2.2.11 (текущий выпуск, который все еще имеет проблему): https://issues.apache.org/jira/browse/JCR-3262

Надеюсь, это поможет!

1 голос
/ 16 октября 2013

Я столкнулся с той же проблемой.Мы использовали 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 голос
/ 25 мая 2012

Мы используем массивы в наших вызовах для хранимых proracle procs и используем собственные api oracle для создания массивов.Эта небольшая проверка исправила проблему для нас при использовании функциональности из автономных приложений, использующих 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 в classpath / dependecies.

    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
        <scope>provided</scope>
    </dependency>
0 голосов
/ 19 декабря 2016

Я работаю с 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 и добавление одного и того же jar-файла в папку lib tomcat.
Кажется, tomcat имеет разные jar для разных версийначиная с 7.0 (ссылка: https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp).

Надеюсь, это кому-нибудь поможет.

0 голосов
/ 19 февраля 2016

Для всех, кто ищет, 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 голосов
/ 30 июля 2015

в вашем определении контекста добавьте теги ниже к существующему определению xml.

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

.

...