公司一系统使用了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