con.rollback()会回滚已经由con.commit()提交的更改吗?



我现在正在从事Legacy项目,它需要对底层JDBC API有深入的了解在某些地方,我看到这样的代码:

try {
con = ....
con.setAutoCommit(false);
//insert_1 pack to db
con.commit();
//insert_2 pack to db
con.commit();
//insert_3 pack to db
con.commit();
} catch (SQLException e) {
try {
con.rollback();
} catch (SQLException e) {
log.warn("SQLException on rolling back the destination connection. ", e);
throw e;
}
throw ex;
}

和conn .rollback();在catch

中未被调用
try {
con = ....
con.setAutoCommit(false);
//insert_1 pack to db
con.commit();
//insert_2 pack to db
con.commit();
//insert_3 pack to db
con.commit();
} catch (SQLException e) {      
throw new MyBusinessException(ex);
}

请从交易的角度解释一下差异好吗?

注:我已经阅读了java文档的回滚,但它没有回答我的问题。

撤消当前事务中所做的所有更改并释放任何当前由此Connection对象持有的数据库锁。这个方法应仅在禁用自动提交模式时使用。抛出:SQLException -如果数据库访问错误发生,此方法是在参与分布式事务时调用此方法在已关闭的连接上调用,或者此connection对象处于自动提交模式参见:setAutoCommit

代码看起来不正确。

  1. 有几个提交被执行。这意味着显式回滚可以将状态回滚到上次提交的开始。我想,这不是回滚应该做的。

  2. 如果没有显式回滚调用,至少在池化数据库连接中(在池化数据库连接中,连接永远不会关闭,而是被重用),已经执行的语句仍然处于事务中。例如,稍后调用这里的rollback会导致奇怪的错误,并且还会回滚最后执行的语句,实际上与当前业务流程无关。我在Hikari连接池实现中看到,脏状态会自动回滚,但可能不能对每个实现都假定这种正确的行为。例如,Apache的DBCP在代码中并不是那么直接,询问维护者他们是否在这样做应该是有帮助的。

  3. I see noclosecall.

对于您的问题,这意味着第二个代码片段应该:

  1. 在单个非池连接中,不要在最后一次提交之后提交最后一个语句,这是正确的(偶然)。
  2. 在池连接中,让事务挂起,这可能导致下一个业务逻辑提交某些内容并重用该连接也会提交此错误。

最新更新