2013-06-10 6 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が:これが原因とされており、どのように私はそれを解決するにはどうすればよい

分離されたインスタンス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(entity)?エンティティ:em.merge(entity))では、 、もし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))を試してください。それは私のために働いた。

関連する問題