Jdbc执行存储过程报数据库事务无法执行的异常
环境:
Eclipse+Jdk1.7+spring-jdbc-3.0.7+同版本的jdbctemplate+Sqlserver 2012
问题:
一个小接口采用jdbctemplate进行对sqlserver的存储过程操作,一般过程执行没问题,但个别存储过程第一次可以执行,第二次再执行就异常;
原因参考:
原因简要总结:
每次调用这个存储过程时,比如方法名为updateAllAttas(),下次执行select或其他dao操作会报数据库事务异常,这是由于jdbc的事务同sqlserver存储过程内部的事务发生冲突导致的,一般情况下如果sqlserver的事务中的代码执行时间过长的话,就会产生这种异常报错;每次执行updateAllAttas时,当前connection会产生问题,在方法执行后会被放入连接池,下次jdbc执行dao操作时,可能会从连接池中取出这个有问题的连接来执行dao操作,所以会报异常;解决方法就是:
1:存储过程中的BEGIN TRANSACTION,COMMIT TRANSACTION删除掉,存储过程中不采用事务机制,事务仅仅在jdbc中控制;
2:java中每次执行完updateAllAttas这个方法后,释放掉这个connection;那么下次dao操作时,由于连接池中没有这个有问题的连接了,所以下次可以正常执行dao操作。
方法1由于要修改存储过程,取消事务,当其他系统调用这个存储过程时,由于取消了事务会带来风险。所以采用方法2.将下面这个方法放到dao层类中,
public void releaseConnection(){
new ConnectionHolder(DataSourceUtils.getConnection(jdbcTemplateBASE.getDataSource())).released();
//释放连接,采用新连接
}
因为是采用jdbctemplate来进行dao操作的,上面方法中jdbctemplateBASE就是由spring管理的jdbctemplate对象;
在每次执行完updateAllAttas这个方法后,再调用releaseConnection这个方法即可;
注意,spring的jdbc的jar包中有好几个类似可以释放连接的方法,经调试,上述ConnectionHolder的released方法有效;其他如DataSourceUtils.releaseConnection(con,datasource)也有释放连接的方法,但是采用这个方法不能解决上述问题