为什么必须在JDBC中使用回滚?

时间:2018-08-07 22:47:29

标签: java jdbc

如果我不使用connection.rollback(),由于尚未提交事务,我可以看到数据库的数据也不会更改任何内容,那为什么我仍然需要使用connection.rollback()

try {

        connection.setAutoCommit(false);


        bankDao.transferMoney(+2000, 1, connection); //account1:+$2000


        if(true){
            throw new RuntimeException(); //make error
        }

        bankDao.transferMoney(-2000, 2, connection);//account2:-$2000


        connection.commit();

    } catch (Exception e) {

        try {

            connection.rollback();
            System.out.println("something wrong, roll back");

        } catch (Exception e1) {

            e1.printStackTrace();

        }

    }

3 个答案:

答案 0 :(得分:4)

您需要显式回滚以确保事务结束。如果您未明确提交或回滚,则-如果继续使用连接-更改可能稍后由应用程序的其他部分提交。显式回滚可以防止这种情况。

在其他情况下,连接关闭将结束事务。但是,连接关闭是提交还是回滚事务取决于驱动程序。 Connectionc.close()文档说:

  

强烈建议应用明确提交   或在调用close方法之前回滚活动事务。   如果调用close方法并且有一个活动事务,   结果是实现定义的。

未明确回滚您的交易也可能导致该交易的寿命超出必要,持有锁等可能阻止其他交易完成其工作。

答案 1 :(得分:1)

您很对,发生异常时不会提交数据,并且该事务最终将由数据库回滚。

内部,InnoDB对错误InnoDB error handling进行隐式rollbak处理,但是除非您真正了解所有情况,否则显式调用connection.rollback()可以确保事务尽早结束(回滚)。 。请注意,当您调用提交或回滚时,事务结束。

在示例代码中,如果由于某种原因该异常不在commit()之外的其他行(例如bankDao.transferMoney)怎么办?

您需要rollabck才能结束交易。

答案 2 :(得分:1)

您有一个客户端进程(您的程序)和一个服务器端进程(正在侦听/等待命令的DBMS组件)。

如果您只是让客户端进程死掉(也就是说,让运行时异常一直传播到整个过程而没有任何catch()或finally {}曾经介入执行connection.close()或类似工作),则服务器端进程仍将等待来自不再存在的客户端进程的命令。它将保留所获得的所有锁,并且只有在服务器端进程最终超时时才会更改。

因此,最好在客户端进程仍然存在时正确地完成所有包装工作。