JPA:关于在删除实体之前合并实体的问题

Posted

技术标签:

【中文标题】JPA:关于在删除实体之前合并实体的问题【英文标题】:JPA: question about merging an entity before removing it 【发布时间】:2011-04-22 01:45:20 【问题描述】:

我知道我必须在删除实体之前合并它,但我从没想过我必须在 EJB 中这样做。首先我有这些:

e = (Event) scholarBean.merge(e);
scholarBean.remove(e);

在我的托管 bean 中。它给了我这个错误

java.lang.IllegalArgumentException: Entity must be managed to call remove: com.scholar.entity.Event@998, try merging the detached and try the remove again.

然后我将这两行放入我的会话 bean 中,它就可以工作了。知道为什么吗?

Managed Bean

myEJB.deleteEvent(e);

myEJB.java

public void deleteEvent(Event e)
    e = (Event) merge(e);
    em.remove(e);

【问题讨论】:

【参考方案1】:

我知道我必须在删除实体之前合并它

不完全是。传递给 remove 的对象必须是一个实体,并且不能被分离。那是不一样的。

但我从没想过我必须在 EJB 中这样做。首先我有这些(...)

让我们看看你在做什么:

1: e = (Event) scholarBean.merge(e); 
2: scholarBean.remove(e);

所以在1: 中,您调用了一个合并实体的EJB(很可能带有事务范围的持久性上下文)。但随后该方法结束,事务提交,Persistence Context 关闭,使返回的实体再次分离

2: 中,您将(仍然)分离的实体传递给EJB 并尝试remove 它,这是不允许的。还有 KaBOOM!

然后我将这两行放入我的会话 bean 中,它就可以工作了。知道为什么吗?

之所以有效,是因为您现在在与 JTA 事务关联的持久性上下文范围内工作,因此您实际上是在将一个托管实体传递给remove

【讨论】:

精彩的答案。非常感谢【参考方案2】:

...您甚至可以将它们组合起来:

像这样:

    public void deleteManCheck(ManCheck manCheck) 
    em.remove(em.merge(manCheck));

【讨论】:

【参考方案3】:

在 servlet 中使用它时,我遇到了相同的事务问题。当使用 MDB 中的 EJB-service-bean 时,它工作得很好,因为事务是在调用 EJB 之前启动的,但是当 EJB 调用来自 servlet 时,没有正在运行的事务。 我通过创建一个启动和提交 UserTransaction 的过滤器在我的 webapp 中解决了这个问题。然后每次调用 EJB 方法都会加入我的 UserTransaction,而不是启动它自己的事务。

【讨论】:

以上是关于JPA:关于在删除实体之前合并实体的问题的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring JPA 中删除实体

JPA删除实体

Datanucleus JPA 命名查询返回已删除的实体

JPA多对多删除实体

在JPA双向@OnetoMany关系中,当我更新父实体时,子实体在数据库中被删除

无法通过持久性删除删除 jpa 子实体