为什么JDBC事务里面要使用 rollback() ?

新手上路,请多包涵
try {

        connection.setAutoCommit(false);


        bankDao.transferMoney(+2000, 1, connection); //帐号1 增加2000


        if(true){
            throw new RuntimeException(); //模拟报错
        }

        bankDao.transferMoney(-2000, 2, connection);//帐号2 减少2000


        connection.commit();

    } catch (Exception e) {

        try {

            connection.rollback();
            System.out.println("回滚事务");

        } catch (Exception e1) {

            e1.printStackTrace();

        }

    }

我发现就算我没有使用connection.rollback(), 由于事务还没有提交, 数据库里面的数据还是不会发生改变, 就是用或者是不用的效果也是一样, 那我为什么还要使用connection.rollback()呢? 谢谢

阅读 5.6k
3 个回答

你的本次两个SQL语句包含在一个事物中。
在你的这个事物中包含了更新操作,而mysql的 innodb是一个行级锁,按照mysql的默认事物级别:Repeated Read
如果你不及时提交或者回滚,那么造成的影响可能有如下两种:

  1. 当另一个事物需要对这一行进行更新的时候是会被阻塞的。一直等到事物超时释放。
  2. 你这个事物如果不及时提交或者回滚。那么其他事物在读取的时候只会读取到你开始事物之前的那一个版本的数据。

所以一个事物要么尽快提交,要么尽快回滚。

顺便你可以去看下oracle关于事物的一个官方文档:
https://docs.oracle.com/javas...

你这个connection虽然还没提交,但是也没关闭,这样其他人就没法修改你正在改的那些行。

开启事务后,一定要跟上 commit 或 rollback,及时释放可能锁住的数据。
你不用rollback()表面和用了rollback()效果一样,但是不用rollback()可能导致被锁住的数据不能及时的释放(需要等事物超时释放),会影响下一次的事物操作。

jdbc api 对rollback()方法的描述。

void rollback()
       throws SQLException
Undoes all changes made in the current transaction and releases any database locks currently held by this Connection object. This method should be used only when auto-commit mode has been disabled.
Throws:
SQLException - if a database access error occurs, this method is called while participating in a distributed transaction, this method is called on a closed connection or this Connection object is in auto-commit mode
See Also:
setAutoCommit(boolean)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题