2011-06-27 66 views
21

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

我試圖找到解決這個問題的途徑,幾乎遍佈整個網站和論壇,但無法得到滿意的答案或解決方案。

+0

爲什麼你只用'dbConn'來打包它呢?如果直接在'dbConn'上調用'getInnermostDelegate',會發生什麼? – Thilo

回答

22

默認情況下,DBCP不允許訪問「實際」底層數據庫連接實例,因此無法訪問Oracle類。

configuring池,可以設置

accessToUnderlyingConnectionAllowed = true 

,然後它的作品。

默認爲false,這是一項潛在的危險操作,行爲異常的程序可以做有害的事情。 (關閉底層或在保護連接已關閉時繼續使用它)小心並且只能在需要直接訪問驅動程序特定擴展時使用

注意:不要關閉底層連接,只能使用原來的連接。

+0

我在資源詳細信息中使用了以下參數,但仍無法使用。 INITIALSIZE = 「5」 maxActive = 「5」 minidle = 「5」 \t \t了maxidle = 「5」 \t MAXWAIT = 「20000」 removeAbandoned = 「真」 removeAbandonedTimeout = 「60」 \t \t maxIdleTime =」 3000「accessToUnderlyingConnectionAllowed =」true「 – Prodigy

+0

這幫了我很多,謝謝! – mtrovo

+0

@Prodigy你有解決方案嗎?我面臨同樣的問題。 – Shibankar

2

我並主張這個位置,以確保任何人需要建議知道最終的解決方案是:

如果你被迫使用持久性管理的非捆綁版本(因爲舊版本庫仍然使用與捆綁佈局不兼容的結構),在這裏你可以做什麼,解決方案很簡單:

下載Jackrabbit Core的源代碼(你可以從Jackrabbit網站獲得它們) 打開OraclePersistenceManager類並找到以下代碼行:

Object blob = createTemporary.invoke(null, 
       new Object[]{con, Boolean.FALSE, durationSessionConstant}); 

(約行377 - 還可以檢查堆棧跟蹤供參考)

連接工廠包含一個靜態方法,允許解開的連接而這正是你所需要的:

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版。

我也確信登錄反對兔崽子2.2.11的錯誤(當前版本仍然有問題): https://issues.apache.org/jira/browse/JCR-3262

希望這有助於!

4

嗯,我遇到了像你一樣的解決方案。我認爲有兩個職位需要你提及它。 1.Config連接池集accessToUnderlyingConnectionAllowed =「true」; 2.關於開源項目的噩夢。可觀的想法。在這種情況下, 是

org.apache.commons.dbcp.DelegatingConnection 

不等於

org.apache.tomcat.dbcp.dbcp.DelegatingConnection 

而在默認的Apache共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 

這是一件很奇怪的事情,但真正的案件。

+0

omg,這是我需要的答案,非常困惑,tomcat改變了路徑... – Reimius

5

看到了這一點後,我可以使用此代碼得到的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(); 

記得公地DBCP-1.4。jar neet在類路徑中

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(); 
    } 

雖然你需要classpath/dependecies中的commons-dbcp。

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

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

+0

這裏沒有什麼值得您希望在oracle.jdbc中導入OracleConnection *接口*,而不是具有相同名稱的具體實現。 – Andrew

1

我曾遇到同樣的問題。我們使用的是Spring,它有一個名爲 NativeJdbcExtractor的類。它有很多實現,下面的實現對TomCat有效。 Websphere,Weblogic應用程序服務器有特定的實現。

<bean id="jdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"></bean> 

在你的DAO,你可以注入豆,用下面的方法

protected NativeJdbcExtractor jdbcExtractor; 
Connection conn=jdbcExtractor.getNativeConnection(oracleConnection); 
+0

這是唯一對我有用的答案。 'accessToUnderlyingConnectionAllowed'沒有改變任何東西,其他答案增加了明確的依賴關係到'commons-dbcp',這是不可接受的。謝謝! –

0

在上下文定義如下代碼添加到現有的XML定義。

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

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(); 
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-dbcp 8.5.8 和Tomcat中的lib文件夾中添加相同的罐子。
似乎tomcat有不同的從7.0開始的不同版本的罐子(參考文獻:https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-dbcp)。

希望它可以幫助別人。

相關問題