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 实体映射的实体指定标识符
异常:org.hibernate.AnnotationException:没有为实体指定标识符:jpa.tenants.DataSourceConfig
Spring Boot JPA Hibernate:即使实体类中存在@Id,也没有为实体错误指定标识符