Apache Commons Проблема с объектом соединения DBCP, Thread: ClassCastException в org.apache.tomcat.dbcp.dbcp.PoolingDataSource $PoolGuardConnectionWrapper
Я использую Apache Commons DBCP (commons-dbcp.jar
) Пул соединений.
Как только я получил соединение из пула, он завернут в
class 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 at oracle.sql.ArrayDescriptor.createDescriptor
Я попытался найти решение по этому поводу на всех сайтах и форумах, но не смог получить удовлетворенный ответ или решение на том же уровне.
Ответы
Ответ 1
По умолчанию, DBCP не разрешает доступ к "реальному" базовому подключению к базе данных, поэтому вы не можете попасть в класс Oracle.
Когда настраивает пул, вы можете установить
accessToUnderlyingConnectionAllowed = true
а затем он работает.
По умолчанию это ложь, это потенциально опасная операция, а неправильные программы могут делать вредные вещи. (закрытие основного или продолжение его использования, когда защищенное соединение уже закрыто) Будьте осторожны и используйте их только в том случае, если вам нужен прямой доступ к конкретным расширениям драйвера
ПРИМЕЧАНИЕ. Не закрывайте базовое соединение, только оригинальное.
Ответ 2
Если вы используете 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
Ответ 3
В этом сообщении я могу получить 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 находится в пути класса
Ответ 4
Хммм, я встречаю то же самое, что и вы. Я думаю, что вам нужно сделать две позиции, о которых вы говорите.
1.Config Connection pool 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
Это такая странная вещь, но реальная работа в этом деле.
Ответ 5
Я предлагаю это здесь, чтобы убедиться, что кто-то, кто ищет советы, знает о конечном решении этого вопроса:
Если вы вынуждены использовать не связанную версию диспетчера персистентности (поскольку старый репозиторий по-прежнему использует эту структуру, которая несовместима с компоновкой в комплекте), вот что вы можете сделать, решение довольно просто:
Загрузите источники для 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
Надеюсь, это поможет!
Ответ 6
Мы используем массивы в наших вызовах для хранения оракулов и используем apacle для создания массивов. Эта небольшая проверка устраняет проблему для нас при использовании функций из автономных приложений, используя 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 в pathpath/dependecies.
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
<scope>provided</scope>
</dependency>
Ответ 7
Я столкнулся с той же проблемой. Мы использовали 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);
Ответ 8
в вашем определении контекста добавьте теги ниже в существующее определение xml.
factory="oracle.jdbc.pool.OracleDataSourceFactory
scope="Shareable"
type="oracle.jdbc.pool.OracleDataSource"
.
Ответ 9
Для остальных, 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();
Ответ 10
Я работаю с 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
и добавьте ту же самую банку в папку lib из tomcat.
Кажется, у tomcat разные банки для разных версий, начиная с 7.0 (ссылка: https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp).
Надеюсь, что это поможет кому-то.