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

我知道我必须在删除它之前合并该实体,但我从未想过我必须在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); } 

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

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

但我从未想过我必须在EJB内部做这件事。 首先,我有这些(…)

让我们看看你在做什么:

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

因此,在1: ,您调用EJB(很可能使用事务范围的持久性上下文)来合并实体。 但随后方法结束,事务提交,持久化上下文被关闭,使得返回的实体再次分离

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

那么我将这两行放在我的会话bean中,它就可以了。 知道为什么吗?

它的工作原理是因为您现在正在与JTA事务关联的持久性上下文的范围内工作,因此您实际上正在传递要remove托管实体。

……你甚至可以把它们结合起来:

像这样:

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

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