spring+jotm+jta+xapool+hibernate+oracle架构中多数据源出现的有关问题

spring+jotm+jta+xapool+hibernate+oracle架构中多数据源出现的问题

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