java.lang.IllegalArgumentException:删除分离的实例com.test.User#5

时间:2013-06-10 15:26:03

标签: jpa sql-delete entitymanager illegalargumentexception

我有一个使用JPA(transaction-type =“JTA”)的java EE项目,hibernate作为提供者。我写我的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

这是如何引起的?如何解决?

6 个答案:

答案 0 :(得分:185)

EntityManager#remove()仅适用于在当前事务/上下文中管理的实体。在您的情况下,您在先前的事务中检索实体,将其存储在HTTP会话中,然后尝试在不同的事务/上下文中删除它。这是行不通的。

您需要检查实体是否由EntityManager#contains()管理,如果没有,则将其设为EntityManager#merge()

基本上,业务服务类的delete()方法应如下所示:

em.remove(em.contains(entity) ? entity : em.merge(entity));

答案 1 :(得分:3)

在我的情况下,当我尝试删除对象时,我得到了同样的错误 使用,

session.delete(obj)

之前没有创建任何交易。

通过首先创建事务(session.beginTransaction()然后删除对象来解决问题。

我希望我的回答可以帮助某人:)

答案 2 :(得分:0)

我遇到了同样的问题。应该重新附加分离的实体。正如@BalusC所提到的,使用EntityManager.merge()应该用于附加分离的实体。 EntityManager.merge()生成SQL查询,该查询获取必须在其上执行EntityManager.remove()的实体的当前状态。但就我而言,它并没有奏效。 请尝试使用EntityManager.remove(EntityManager.find(Class<T>,arg))。它对我有用。

答案 3 :(得分:0)

有时它只是因为你缺少@Transaction注释来添加,删除,更新操作。

答案 4 :(得分:0)

根据我的经验,如果我从数据库中查询一个对象,然后关闭了实体管理器,然后删除了一个数据库,则会发生此问题。或者,如果我将已加载的对象复制到另一个实例,然后执行删除操作,也会发生此问题。 我认为有两件事要注意:

  • 该对象必须位于由实体管理器创建的同一会话中
  • 当实体管理器的会话仍处于打开状态时,不得将对象转移到另一个对象。

欢呼

答案 5 :(得分:-2)

有时你可以从分离的实例中获取id,然后使用直接查询到数据库。例如

String petId = pet.getId().toString();
entityManager.createQuery("DELETE FROM Pet pet WHERE id=" + petId).executeUpdate();

您可以清理上下文

if (em.contains(pet)){
     em.remove(pet);
}