java - 如果 OneToMany 相关实体被分离,则级联时出现 PersistenceException

标签 java hibernate jpa

给出这个简单的例子(https://github.com/lelmarir/jpa-cascade-bug-test):

runInTransaction(em, () -> {
   Parent p = em.find(Parent.class, id);
   Child firstChild = p.getChilds().get(0);

   em.detach(firstChild);
   em.flush();
});

它将因以下错误而失败:

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.example.Child
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1356)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1339)
    at com.example.App.lambda$1(App.java:47)
    at com.example.App.runInTransaction(App.java:62)
    at com.example.App.main(App.java:40)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.example.Child
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:120)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:113)
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:755)
    at org.hibernate.engine.spi.CascadingActions$8.cascade(CascadingActions.java:341)
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:492)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:416)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218)
    at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:525)
    at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:456)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:419)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218)
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:151)
    at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:158)
    at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:148)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:81)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102)
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1352)
    ... 4 more

我应该将此报告为 Hibernate bug 还是预期行为?

最佳答案

is it an expected behaviour?

是的。

让我引用 JPA Specification 中的两段摘录适用于此处:

第一个:

The state of persistent entities is synchronized to the database at transaction commit. (...) If X is a managed entity, it is synchronized to the database. (...) For all entities Y referenced by a relationship from X, if the relationship to Y has been annotated with the cascade element value cascade=PERSIST or cascade=ALL, the persist operation is applied to Y

第二个:

The semantics of the persist operation, applied to an entity X are as follows: (...) If X is a detached object, the EntityExistsException may be thrown when the persist operation is invoked, or the EntityExistsException or another PersistenceException may be thrown at flush or commit time.

(强调我的)

我注意到很多人对这种行为感到困惑,实际上期望 JPA 刷新的行为就像在父实体上调用 merge() 一样。 但是,由于父实体已被管理,因此此时没有任何内容可以合并。

关于java - 如果 OneToMany 相关实体被分离,则级联时出现 PersistenceException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61957841/

相关文章:

java - 如何找到所有基于图像的 PDF?

java - 无法将类型 : value: java. sql.Timestamp 转换为 org.joda.time.DateTime

java - 如何将 Magnolia cms 与 hibernate 搜索集成?

java - 我们是否正在走向类似于 dll hell 的 java 平台中的 jar hell ?

java - Hibernate 合并正在生成新行而不是更新

mysql - 级联删除具有非级联外键的行

java - 在 JSP 中将对象作为变量传递

java - 迭代时检查List中是否还有剩余项

java - Spring 启动 : Hibernate and Flyway boot order

spring - 为什么 Spring 需要 HIbernateTransactionManager?