我知道我必须在删除它之前合并该实体,但我从未想过我必须在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);
}
答案 0 :(得分:17)
我知道我必须在删除它之前合并该实体
不完全是。传递给remove的对象必须是一个实体,不能分离。那是不同的。
但我从未想过我必须在EJB内部这样做。首先,我有这些(...)
让我们看看你在做什么:
1: e = (Event) scholarBean.merge(e);
2: scholarBean.remove(e);
因此,在1:
中,您调用EJB(很可能使用事务范围的持久性上下文)来合并实体。但随后方法结束,事务提交,持久化上下文关闭,再次使返回的实体分离。
在2:
中,您将(仍然)分离的实体传递给EJB并尝试remove
它,这是不允许的。和KaBOOM!
然后我将这两行放在我的会话bean中,并且它可以工作。知道为什么吗?
它的工作原理是因为您现在正在与JTA事务关联的持久性上下文的范围内工作,因此您实际上将托管实体传递给remove
。
答案 1 :(得分:7)
......你甚至可以将它们结合起来:
像这样:
public void deleteManCheck(ManCheck manCheck) {
em.remove(em.merge(manCheck));
}
答案 2 :(得分:2)
当在servlet中使用它时,我遇到了相同的事务问题。当从MDB使用EJB-service-bean时,它工作正常,因为事务是在调用EJB之前启动的,但是当EJB调用来自servlet时,没有正在运行的事务。 我通过创建一个启动并提交UserTransaction的过滤器在我的webapp中解决了这个问题。然后,对EJB方法的每次调用都会加入我的UserTransaction,而不是启动它自己的事务。