公司一系統使用了spring+jotm+jta+xapool+hibernate+oracle架構,系統出現了500錯誤,錯誤資訊如下:
java.sql.SQLException: SQLException in StandardPoolDataSource:getConnection
exception: java.sql.SQLException: Cannot get connection for URL jdbc:oracle:thin:@10.4.1.110:1521:testdb
: 調用中無效的參數
at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:218)
at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:168)
at org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource.getConnection(AbstractRoutingDataSource.java:133)
……
其中資料源配置的部分bean如下(網上找的示例,和我的格式一樣):
<bean id="dataSource_stat" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
<property name="dataSource">
<bean id="innerDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
<property name="transactionManager">
<ref local="jotm"/>
</property>
<property name="driverName">
<value>oracle.jdbc.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@10.4.1.110:1521:testdb</value>
</property>
<property name="minCon" value="1">
</bean>
</property>
<property name="user">
<value>t_wms</value>
</property>
<property name="password">
<value>111</value>
</property>
</bean>
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBea n"/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransaction Manager">
<property name="userTransaction"><ref local="jotm"/></property>
</bean>
錯誤比較奇怪的地方在于:
1.部分子產品出現該錯誤,部分子產品不會出現。
2.出現該錯誤的子產品,有時候會正常,有時候會出現上述錯誤。
3.出現錯誤的子產品中,使用級聯操作的頁面出現的機率高,查詢單獨表的頁面出現錯誤的機率小。
1.排查問題的過程中,首先排除了代碼問題,原因是系統部署使用另外擷取資料源的方式,如,把資料源配置在resion中,是不會出現該問題的。
2.懷疑是jar包沖突的問題。在排查過程中,發現資料庫連接配接的jar包之間沒有問題,與資料源配置在resion中系統的lib包中資料連接配接的jar包是一樣的,包括ssh的包。
3.懷疑是xa事務控制的問題。
在調查xapool的問題時,發現也有coder也出現了類似的問題,不過時間比較早。畢竟xapool 1.5版本是2005年釋出的,2006年釋出了1.6beat版本後就沒再更新過。
主要解決方案有
方案1.
如果是使用的1.5版本的
Oracle9i有名的記憶體溢出bug導緻:Xapool對PreparedStatement進行了Cache,同時Oracle有一個出名的記憶體漏洞,PreparedStatement使用之後必須關閉,如果不關閉連續進行SQL查詢會造成前面SQL的遊标不能釋放;
Xapool1.5的修改如下:
修改StandardConnectionPoolDataSource類的public static final int DEFAULT_PREPAREDSTMTCACHESIZE = 0,(當然也可以用配置的方式來注入)
這樣就關閉了PreparedStatement的Cache,而且也不會造成什麼1.4中關閉連接配接時的異常等等.
或者:
下載下傳xapool源碼包,然後在org.enhydra.jdbc.pool.GenericPool中,找到life = (Long) unlocked.get(o); 代碼
之後在下面加入:
if (life == null) continue;
建議使用1.6版本的吧,畢竟自己需要檢視源代碼和修改,如果不慎可能造成不可預知的後果。
方案2.可以把資料源修改為
<bean id="dataSource_stat" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
<property name="transactionManager">
<ref local="jotm"/>
</property>
<property name="driverName">
<value>oracle.jdbc.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@10.4.1.110:1521:testdb</value>
</property>
</property>
<property name="user">
<value>t_wms</value>
</property>
<property name="password">
<value>111</value>
</property>
<property name="minCon" value="1">
</bean>
這個方案是自己測試發現的,可以使用,但是貌似沒有走資料連接配接池。
方案3.
資料連接配接池中資料源中都配置使用者名和密碼,即StandardXAPoolDataSource中要配置user和password,StandardXADataSource中也要配置user和password如:
<bean id="dataSourcePool" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
<property name="dataSource">
<bean id="innerDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
<property name="transactionManager">
<ref local="jotm"/>
</property>
<property name="driverName">
<value>oracle.jdbc.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@10.4.1.110:1521:testdb</value>
</property>
<property name="user">
<value>t_wms</value>
</property>
<property name="password">
<value>111</value>
</property>
<property name="minCon" value="1">
</bean>
</property>
<property name="user">
<value>t_wms</value>
</property>
<property name="password">
<value>111</value>
</property>
</bean>
這個問題挺奇怪的,如果有朋友有其他好的解決方案,歡迎交流~~
參考位址:http://www.blogjava.net/hunteva/archive/2009/01/20/62936.html
http://forum.springsource.org/archive/index.php/t-28145.html
http://fableking.iteye.com/blog/954153