JPA 和 Hibernate 实体标识符是不是在回滚后重置为 null?

Posted

技术标签:

【中文标题】JPA 和 Hibernate 实体标识符是不是在回滚后重置为 null?【英文标题】:Are JPA and Hibernate entity identifiers reset to null after a rollback?JPA 和 Hibernate 实体标识符是否在回滚后重置为 null? 【发布时间】:2014-01-05 07:59:02 【问题描述】:

如果我进行回滚,会话中的实体会发生什么情况?他们会在交易前回到状态吗?特别是他们有新的 id 吗?

例子:

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

更新

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

【问题讨论】:

你也测试过吗?它奏效了吗?您是否还尝试在 rollback() 之前执行 flush()(以便获得 ID)? @AndreiI 我已经用 Hibernate 4 对其进行了测试。id 已分配给实体,并且在回滚后没有更改。 【参考方案1】:

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

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

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

【讨论】:

安德烈是完全正确的。但我只是想通过 Hibernate 补充一点,您可以启用设置 hibernate.use_identifier_rollback(设置为 true)来重置回滚时生成的标识符的状态。 @SteveEbersole 很酷的提示,但据我了解,如果实体被删除,则使用hibernate.use_identifier_rollback?我不确定回滚时会发生什么。见:link to hibernate 3 docu【参考方案2】:

这不是错误,而是功能

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

那么,回到你的问题:

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

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

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

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

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

【讨论】:

【参考方案3】:

所有托管实体都将分离。

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

(请参阅 OpenJPA 文档:http://openjpa.apache.org/documentation.html

【讨论】:

好的,谢谢。但是实体会发生什么?实体会变回交易前的状态吗? 我必须测试它们,或者你可以,但我怀疑内存中的实体将保持在回滚时的任何状态。数据存储中的副本当然会恢复到交易前的状态。

以上是关于JPA 和 Hibernate 实体标识符是不是在回滚后重置为 null?的主要内容,如果未能解决你的问题,请参考以下文章

org.hibernate.AnnotationException:没有为使用 JPA XML 实体映射的实体指定标识符

Hibernate JPA 序列(非 Id)

异常:org.hibernate.AnnotationException:没有为实体指定标识符:jpa.tenants.DataSourceConfig

Spring Boot JPA Hibernate:即使实体类中存在@Id,也没有为实体错误指定标识符

@IdClass 使用 JPA 和 Hibernate 生成“实例标识符已更改”

hibernate中实体类注解