Hibernate事务回滚是否删除“session.flush()”ed实体?

时间:2012-03-28 13:02:16

标签: java hibernate orm

我对transaction.rollback感到困惑。这是一个伪代码示例:

transaction = session.beginTransaction()    
EntityA a = new EntityA();    
session.save(a);    
session.flush();    
transaction.rollback();

此代码有效时会发生什么?我是否在数据库中拥有该实体?

3 个答案:

答案 0 :(得分:30)

简短回答:不,你不会在数据库中拥有实体。

更长的答案:hibernate足够智能,不会向DB发送插入/更新,直到它知道事务是否将被提交或回滚(尽管可以通过设置不同的FlushMode来改变此行为),在您的情况下通过调用flush你强迫SQL被发送到数据库,但你仍然有数据库事务来保护你,当你调用回滚时,数据库事务将回滚删除在其自身内执行的更改,因此实际上不会保存任何内容。请注意,根据您配置的事务隔离级别,其他事务可能会以某种方式查看您在保存和回滚之间保存的EntityA。 另请注意,当您尝试从DB读取时会自动调用flush,在99%的情况下,不需要显式调用它。我想到的一个例外是使用自动回滚测试进行单元测试时。

答案 1 :(得分:20)

当你调用session.save(a)时,Hibernate基本上会记住会话内的某个地方必须保存这个对象。它可以决定是否要立即,稍后或提交时发出INSERT INTO...。这是性能改进,允许Hibernate批量插入或在事务回滚时避免它们。

当你致电session.flush()时,Hibernate被迫对数据库发出INSERT INTO...。实体存储在数据库中,但尚未提交。根据事务隔离级别,其他正在运行的事务将不会看到它。但现在数据库知道关于记录。

当您调用transaction.rollback()时,Hibernate回滚数据库事务。数据库处理回滚,从而删除新创建的对象。

现在考虑没有flush()的方案。首先,你永远不会触摸数据库,因此性能更好,回滚基本上是无操作。另一方面,如果事务隔离级别为READ UNCOMMITTED,则其他事务甚至可以在提交/回滚之前查看插入的记录。如果没有flush(),这将不会发生,除非Hibernate没有暗中决定flush()

答案 2 :(得分:8)

我认为您对flushcommit感到困惑。

flush()将状态与数据库同步,但它没有进行提交。事务仍然可以看到状态,因此您可以调用rollback来回滚。

所以你问题的答案是:不,你没有数据库中的实体(a)。