Apache Commons DBCP objet de connexion problème, Thread: ClassCastException dans org.Apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper
J'utilise Apache Commons DBCP (commons-dbcp.jar
) piscine de connexion.
une fois que j'ai obtenu une connexion de la piscine il est enveloppé dans le
classe org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper
.
Mon exigence est de passer un tableau de Chaînes de procédure stockée pl/sql Oracle.
Voici ce que je fais dans l'extrait de code suivant:
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();
Sur l'exécution du code ci-dessus, j'obtiens l'exception suivante:
java.lang.ClassCastException: org.Apache.commun.dbcp.PoolingDataSource$PoolGuardConnectionWrapper ne peut pas être envoyé à oracle.jdbc.OracleConnection chez oracle.SQL.ArrayDescriptor.createDescriptor
j'ai essayé de trouver des solutions sur ce qui va à travers presque des sites et des forums, mais n'a pas pu obtenir la réponse satisfaite ou la solution sur le même.
10 réponses
par défaut, DBCP ne permet pas l'accès à l'instance de connexion "réelle" de la base de données sous-jacente, de sorte que vous ne pouvez pas accéder à la classe Oracle.
Quand configuration la piscine, vous pouvez définir
accessToUnderlyingConnectionAllowed = true
et puis il travaille.
La valeur par défaut est fausse, c'est une opération potentiellement dangereuse et les programmes qui se comportent mal peuvent faire des choses néfastes. (fermer le sous-jacent ou continuer à l'utiliser lorsque la connexion protégée est déjà fermée) soyez prudent et utiliser uniquement quand vous avez besoin d'un accès direct à pilote spécifique extensions
NOTE: Ne fermez pas la connexion sous-jacente, seulement la connexion originale.
si vous utilisez une connexion JDBC compatible Java 6, Vous pouvez utiliser le code suivant:
OracleConnection oracleConnection = null;
try {
if (connection.isWrapperFor(OracleConnection.class)) {
oracleConnection = connection.unwrap(OracleConnection.class);
}
} catch (SQLException ex) {
// do something
}
return oracleConnection;
à partir de Maintenant, utilisez le oracleConnection
au lieu de l'original connection
.
voir http://docs.oracle.com/javase/6/docs/api/java/sql/Wrapper.html
voir ce post je peux obtenir la connexion Oraclec avec ce 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();
souvenir de la chambre des communes-dbcp-1.4.jar neet pour être dans le chemin de classe
org.apache.commons.dbcp.DelegatingConnection
n'est pas égal à
org.apache.tomcat.dbcp.dbcp.DelegatingConnection
alors que par défaut apache common-dbcp.jar, tu ne trouveras jamais la classe suivante.Mais juste la classe est la clé. Donc, nous devons trouver la classe quelque part. Je finale de trouver le paquet tomcat-dbcp.pot. Vous pouvez l'obtenir à partir d' http://www.docjar.com/ Après
import org.apache.tomcat.dbcp.dbcp.DelegatingConnection
,vous pouvez forcer dbConn et obtenir la connexion sous-jacente
oracle.jdbc.driver.OracleConnection delConn =
(oracle.jdbc.driver.OracleConnection)
((org.apache.tomcat.dbcp.dbcp.DelegatingConnection)c_stmt.getConnection()).getDelegate();
alors nous pouvons utiliser delConn pour obtenir le tableau descripteur N'oubliez pas une chose,là,nous n'avons pas besoin de l'
org.apache.commons.dbcp.DelegatingConnection Class
C'est une chose étrange,mais vrai travail à l'affaire.
je pose ceci ici pour m'assurer que tous ceux qui cherchent des conseils connaissent la solution ultime à ceci:
si vous êtes forcé d'utiliser la version non empaquetée du gestionnaire de persistance (parce qu'un ancien dépôt utilise toujours Cette structure qui est incompatible avec la mise en page empaquetée), voici ce que vous pouvez faire, la solution est assez simple:
Téléchargez les sources de Jackrabbit Core (vous pouvez les trouver sur le site de Jackrabbit)) Ouvrez le OraclePersistenceManager class et trouver la ligne de code suivante:
Object blob = createTemporary.invoke(null,
new Object[]{con, Boolean.FALSE, durationSessionConstant});
(autour de la ligne 377 - peut également vérifier le Stactrace pour référence)
ConnectionFactory contient une méthode statique qui permet de déballer une connexion qui est exactement ce dont vous avez besoin:
Object blob = createTemporary.invoke(null,
new Object[]{org.apache.jackrabbit.core.util.db.ConnectionFactory
.unwrap(con), Boolean.FALSE, durationSessionConstant});
vous aurez besoin de Maven 2+ pour compiler les sources, Je l'ai fait et n'ai eu aucun problème de dépendance, notez que j'ai compilé la version 2.2.10 de Jackrabbit.
https://issues.apache.org/jira/browse/JCR-3262Espérons que cette aide!
nous utilisons des tableaux dans nos appels à des procs stockés dans oracle et nous utilisons l'api propriétaire d'oracle pour construire des tableaux. Cette petite vérification nous a permis de régler le problème lors de l'utilisation de la fonctionnalité des applications autonomes utilisant 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();
}
vous aurez besoin de commons-dbcp dans classpath/dependecies.
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
<scope>provided</scope>
</dependency>
j'avais rencontré le même problème. Nous utilisions spring et il a une classe appelée NativeJdbcExtractor. Il a de nombreuses implémentations et la suivante fonctionne pour TomCat. Il existe des implémentations spécifiques pour Websphere,les serveurs d'applications Weblogic.
<bean id="jdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"></bean>
protected NativeJdbcExtractor jdbcExtractor;
Connection conn=jdbcExtractor.getNativeConnection(oracleConnection);
dans votre définition de contexte, ajoutez les balises suivantes à votre définition xml existante.
factory="oracle.jdbc.pool.OracleDataSourceFactory
scope="Shareable"
type="oracle.jdbc.pool.OracleDataSource"
.
Pour quelqu'un d'autre à la recherche, getDelegate()
et getInnermostDelegate()
les deux de retour NULL
dans mon code. Cependant, du débogueur j'ai trouvé la connexion Oraclec comme ci-dessous. Nous utilisons Spring JdbcTemplate tout au long de l'application, qui a la source de données injectée. On est sur spring-jdbc-4.1.5.PUBLIER.jar et ojdbc6.pot.
Connection conn = getJdbcTemplate().getDataSource().getConnection();
OracleConnection oracleConnection = ( OracleConnection ) conn.getMetaData().getConnection();
je travaille avec tomcat 8.5.8 et je faisais face à cette question.
La solution ci-dessous a fonctionné comme un charme.
Le Code:
Delegating Connection delegate_conn = new Delegating Connection(connection)
conn = delegate_conn.getInnermostDelegate();
oracle.sql.ArrayDescriptor desc = oracle.sql.ArrayDescriptor.createDescriptor("TABLE_VIEW", conn);
La Solution:
Ajout de la dépendance tomcat-dbcp 8.5.8
et ajouter le même bocal dans le dossier lib de tomcat.
Il semble que tomcat ait des bocaux différents pour différentes versions à partir de 7.0 (référence: https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp).
j'Espère que ça aide quelqu'un.