java.lang.IllegalArgumentException:删除分离的实例 com.test.User#5
Posted
技术标签:
【中文标题】java.lang.IllegalArgumentException:删除分离的实例 com.test.User#5【英文标题】:java.lang.IllegalArgumentException: Removing a detached instance com.test.User#5 【发布时间】:2013-06-06 07:35:38 【问题描述】:我有一个使用 JPA (transaction-type="JTA")、hibernate 作为提供者的 java EE 项目。我写我的 bean 来处理 CRUD 的事情。在 JBOSS 7 AS 中运行的程序。
我有一个 EntityManagerDAO :
@Stateful
public class EntityManagerDao implements Serializable
@PersistenceContext(unitName = "dtdJpa")
private EntityManager entityManager;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public Object updateObject(Object object)
object = entityManager.merge(object);
return object;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void createObject(Object object)
entityManager.persist(object);
public void refresh(Object object)
entityManager.refresh(object);
public <T> T find(Class<T> clazz, Long id)
return entityManager.find(clazz, id);
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void deleteObject(Object object)
entityManager.remove(object);
但是当我调用deleteObject
时,就会出现这个异常。
java.lang.IllegalArgumentException: 删除一个分离的实例 com.test.User#5
这是怎么引起的,我该如何解决?
【问题讨论】:
【参考方案1】:EntityManager#remove()
仅适用于在当前事务/上下文中管理的实体。在您的情况下,您在较早的事务中检索实体,将其存储在 HTTP 会话中,然后尝试在不同的事务/上下文中将其删除。这根本行不通。
您需要检查该实体是否由EntityManager#contains()
管理,如果不是,则使其由EntityManager#merge()
管理。
基本上,您的业务服务类的delete()
方法应如下所示:
em.remove(em.contains(entity) ? entity : em.merge(entity));
【讨论】:
@BalusC In em.remove(em.contains(entity) ? entity : em.merge(entity)); ,如果 em(contains(entity) 为假,那么您是否要删除 entityToBeRemoved = em.merge(entity) , entityToBeRemoved?您是否要删除从 em.merge(entity) 返回的内容? 因为根据我提到的问题中的答案,您需要:a = em.merge(a); // 合并并将 a 分配给附加的实体 em.remove(a); // 移除附加的实体 @BalusC 在使用 em.remove(em.contains(entity) ? entity : em.merge(entity));有没有相关的危险。因为我遇到了这个错误,所以我更改了您的解决方案并且它有效。但我团队中的 Java 专家不太确定。 @BalusCem.remove(em.getReference(...))
也可以吗?
@BalusC man.. 你是个天才。我遇到过同样的问题。但我将事务移至服务层并解决了我的问题。实际上我的情况有点不同,从 UI 我得到的只是用户的 ID,所以在我的服务中,我对数据库进行了 2 次调用。一是检查用户是否存在,二是删除。正如您所说,由于事务位于 DAO 层,因此它是一个单独的事务。所以我把它移到服务层并且它工作了..再次感谢你的清晰解释。【参考方案2】:
就我而言,当我尝试删除一个对象时,我遇到了同样的错误 使用,
session.delete(obj)
在此之前不创建任何事务。
而问题是通过先创建事务(session.beginTransaction()然后删除对象来解决的。
我希望我的回答对某人有所帮助:)
【讨论】:
【参考方案3】:有时只是因为您缺少用于添加、删除、更新操作的 @Transaction 注释。
【讨论】:
【参考方案4】:我遇到了同样的问题。应重新连接分离的实体。正如@BalusC 提到的,应该使用EntityManager.merge()
来附加分离的实体。 EntityManager.merge()
生成 SQL 查询,该查询获取实体的当前状态,必须对其执行 EntityManager.remove()
。但就我而言,它没有用。
请改用EntityManager.remove(EntityManager.find(Class<T>,arg))
。它对我有用。
【讨论】:
【参考方案5】:根据我的经验,如果我从数据库中查询一个对象,然后关闭实体管理器,然后执行数据库删除,就会出现问题。或者,如果我将该加载的对象复制到另一个实例然后执行删除,也会发生此问题。 在我看来,有两点需要注意:
对象必须在由实体管理器创建的同一会话中 在实体管理器的会话仍处于打开状态时,不得将对象转移到另一个对象。干杯
【讨论】:
以上是关于java.lang.IllegalArgumentException:删除分离的实例 com.test.User#5的主要内容,如果未能解决你的问题,请参考以下文章