2013-06-10 3 views
33

JPA (트랜잭션 유형 = "JTA")를 사용하는 java EE 프로젝트가 있고 공급자로 최대 절전 모드입니다. CRUD 일을 처리하기 위해 제 콩을 씁니다. JBOSS 7 AS에서 실행되는 프로그램.java.lang.IllegalArgumentException : 분리 된 인스턴스 제거 com.test.User # 5

나는 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가 : detached 인스턴스에 com.test.User # 5

어떻게 이런 일이 발생하고 나는 그것을 어떻게 해결할 수를 제거?

답변

144

EntityManager#remove()은 현재 트랜잭션/컨텍스트에서 관리되는 엔티티에서만 작동합니다. 귀하의 경우 이전 트랜잭션에서 엔티티를 검색하여 HTTP 세션에 저장 한 다음 다른 트랜잭션/컨텍스트에서 엔티티를 제거하려고 시도합니다. 이것은 작동하지 않습니다.

엔티티가 EntityManager#contains()으로 관리되는지 확인하고, 그렇지 않은 경우 엔 EntityManager#merge()으로 관리해야합니다.

기본적으로, 비즈니스 서비스 클래스의 delete() 방법은 다음과 같아야합니다 내가 사용하여 객체 을 삭제하려고 할 때

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

@BalusC em.remove에서 (em.contains (엔터티)? 엔터티 : em.merge (엔터티)); , em (contains (entity))가 false 인 경우 entityToBeRemoved = em.merge (entity), entityToBeRemoved를 제거 하시겠습니까? em.merge (엔터티)에서 반환되는 항목을 제거 하시겠습니까? –

+0

앞서 언급 한 질문의 대답에 따르면 a = em.merge (a); // 첨부 된 엔티티에 a를 병합하고 할당하기 em.remove (a); // 첨부 된 엔티티를 제거하십시오. –

+1

잘 수행되었습니다. 이것은 매우 사실이며 이것은 좋은 것입니다. 해결책 imho. –

1

를 내 경우, 나는 같은 오류를 가지고

session.delete(obj) 

그 전에 어떤 트랜잭션도 생성하지 않아야합니다.

그리고 문제는 개체를 첫 번째 (session.beginTransaction를() 트랜잭션을 생성하고 삭제하여 해결된다. 내 대답은 도움이되기를 바랍니다

사람 : 때때로

-2

방금에서 ID를 얻을 수 있습니다 인스턴스를 분리 한 다음 데이터베이스에 직접 쿼리를 사용하십시오. 예를

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

로서 당신은 내가 같은 문제에 직면 컨텍스트

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

BTW. 문자열 연결을 사용하여 매개 변수의 값을 설정하는 것은 좋은 생각이 아닙니다. 이 응용 프로그램은 SQL 주입 공격에 취약해질 수 있습니다. – Vic

0

정리할 수 있습니다 후. 분리 된 개체는 다시 부착해야합니다. @BalusC가 언급했듯이, EntityManager.merge()을 사용하여 분리 된 엔티티를 부착해야합니다. EntityManager.merge()EntityManager.remove()이 수행되어야하는 엔터티의 현재 상태를 가져 오는 SQL 쿼리를 생성합니다. 하지만 제 경우에는 효과가 없었습니다. 대신 EntityManager.remove(EntityManager.find(Class<T>,arg))을 시도하십시오. 그것은 나를 위해 일했습니다.

관련 문제