波总:
有一个需求是这样的,在项目中开启了事务,做了以下操作
A方法:操作数据库
B方法:操作数据库
C方法操作数据库。
参考了您之前提到的 DbKit.getConfig().getConnection().commit();说可以。
所以在B方法中使用了 DbKit.getConfig().getConnection().commit();,然后再C方法报错后,A和B都提交了事务。如果想只要B方法提交事务,A和C都回滚,怎么写呢?
B方法如下:
private Integer add(String name, String code) throws Exception { int val=1; Connection con = DbKit.getConfig().getThreadLocalConnection(); PreparedStatement pst = con.prepareStatement("insert into serial(name,code,val) values(?,?,?)"); pst.setString(1, name); pst.setString(2, code); pst.setInt(3, val); pst.execute(); con.commit(); DbKit.getConfig().close(pst,con); return val; }
注意看 DbKit.getConfig() 这个方法的实现:
Connection conn = threadLocal.get();
if (conn != null)
return conn;
return showSql ? new SqlReporter(dataSource.getConnection()).getConnection() : dataSource.getConnection();
该方法是优先从 ThreadLocal 中获取 connection 对象,假定你的 A 方法最先调用该方法,后面的 B、C 如果与 A 处在同一个线程,那么获取到的对象与 A 中将是同一个。所以 A、B、C 的事务将融合为一个事务
解决办法自然就简单了:想办法获取独立的 Connection 对象,具体代码如下:
DbKit.getConfig().getDataSource().getConnection()
以上代码将获取到一个全新的 connection 对象,对该对象进行数据库操作,然后进行 commit() 将是它自己独享的