回滚后JPA / Hibernate中的实体状态和实体ID值

时间:2013-12-17 13:59:35

标签: hibernate jpa persistence

如果我进行回滚,会话中的实体会发生什么?交易前他们会回到州吗?特别是他们会得到新的ids吗?

示例:

session.startTransaction();
Entity e = new Entity(); //e.id == null
session.save (e);        //suppose it was ok
session.rollback();      // e.id == ???

更新

我已经进行了Hibernate 4测试。在测试之后,实体已成为新的id。

3 个答案:

答案 0 :(得分:5)

我将简单引用JPA实现(3.3.2事务回滚):

  

对于事务范围和扩展持久性上下文,   事务回滚导致所有预先存在的托管实例和   删除了实例[31]以使其脱离。实例的状态将是   事务处的实例状态   回滚。事务回滚通常会导致持久性   上下文在回滚时处于不一致状态。在   特别是,版本属性和生成状态的状态(例如,   生成的主键)可能不一致。那些实例   以前由持久化上下文管理(包括新实例)   因此,在该交易中持久的那些可能不是   可以像其他分离对象一样重复使用 - 例如,   传递给合并操作时它们可能会失败。[32]

这实际上意味着,在调用em.rollback()之前,它取决于您是否拥有ID(这取决于FlushMode和JPA实现)。如果分配了ID,则ID将保持设置。如果没有,那么你将没有身份证。

答案 1 :(得分:4)

这不是错误,而是功能

身份和序列是无事务的。如果不是,那么一个事务将持有锁,如果该事务在 5 分钟内没有释放它,则没有其他事务可以为同一张表插入任何其他记录。

那么,回到你的问题:

如果我进行回滚,会话中的实体会发生什么?

实体标识符根本没有改变。现在,回滚事务意味着刷新还没有完成。因此,虽然提交多个连续事务很好,但如果抛出异常并且您回滚,那么 Session 应该关闭,as the Hibernate Session Javadoc says

<块引用>

如果 Session 抛出异常,则必须回滚事务并丢弃会话。异常发生后,Session内部状态可能与数据库不一致。

他们会回到交易前的状态吗?

不,当然不是。自动生成的 ID 未绑定到当前正在运行的事务。

答案 2 :(得分:1)

所有托管实体都将分离。

除非您使用扩展持久性上下文,否则回滚也会结束持久性上下文。

(参见OpenJPA docs:http://openjpa.apache.org/documentation.html