2012-04-12 13 views
4
私は1つのエンティティを削除して作成する必要が

別:私はem.flush()がコメントしたままならば、私はcom.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException(新旧のオブジェクトが同じキー値を持つ)を取得JPA:EclipseLinkの尊重ないem.remove()

@Stateless 
public class StatelessBean { 
    @PersistenceUnit(unitName = "Unit001") 
    EntityManagerFactory emf; 

    protected void test() { 
    EntityManager em = emf.createEntityManager(); 
    MyObj obj1 = em.find(MyObj.class, 100); 
    MyObj obj2 = new MyObj(); 
    obj2.setKey("the same unique key as in obj1"); 
    em.remove(obj1); 
    // em.flush(); 
    em.persist(obj2); // works fine when flush() is uncommented 
    em.close(); 
    } 
} 

このような異常動作の原因は何でしょうか?

サーバー:Glassfishの3.1.2

Eclipseの永続性サービス - 2.3.2.v20111125-r10461

のpersistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> 
    <persistence-unit name="Unit001"> 
    <jta-data-source>jdbc/Unit001DS</jta-data-source> 
    <properties> 
     <property name="eclipselink.logging.level" value="INFO"/> 
     <property name="eclipselink.target-database" value="MySQL"/> 
    </properties> 
    </persistence-unit> 
</persistence> 

接続プール:

${ASADMIN} --port ${DOMAIN_ADMIN_PORT} create-jdbc-connection-pool --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource --restype javax.sql.ConnectionPoolDataSource --property "User=user:Password=pass:URL=jdbc\:mysql\://${DB_ADDRESS}/db" Unit001DS 
${ASADMIN} --port ${DOMAIN_ADMIN_PORT} create-jdbc-resource --connectionpoolid Unit001DS jdbc/Unit001DS 

答えて

5

その理由は、Eclipselinkが、コミット中の操作の順序をEclipselink documentation

デフォルトでは、削除操作の前に、参照整合性が確実に維持されるように、挿入操作と更新操作が最初に実行されます。これが好ましいアプローチです。

あなたは(あなたがすでに出て見られるような)フラッシュすることにより、またはEclipseLinkのための特別なパラメータを設定することにより、いずれかのこの動作を変更することができます

あなたが 削除することで、ユニークな制約を持つオブジェクトを置換することを余儀なくされている場合置換操作を挿入すると、削除操作の前に挿入操作が発生すると、制約が発生することがあります( )。 この場合、挿入操作の前にオペレーションを削除するには、setShouldPerformDeletesFirstを呼び出してください。

+0

ありがとうございます。しかし、「他のJPAの実装はこれと同じです」というのは疑問です.JAのプロバイダとしてHibernateを実行しているプロジェクトは全く同じです。 – Osw

+0

あなたは正しいかもしれません、私はそれについてはわかりません、ちょうど別の投稿でそれを読んでください。私の答えを編集します。 –

+0

eclipselinkがsqlをJavaコードフローとして生成するような設定オプションはありますか?私は時間がたっぷりで、SQLの削除だけを調整することなく、休止状態に互換性のあるソリューションを持っていたいと思っています。 – Osw

1

のEclipseLinkは維持し、にコミットする順序を最適化します。

1 - 参照整合性制約を維持する:あなたは二つの関連するオブジェクト(または多くのオブジェクトの一つの大きな相互接続グラフ)を挿入した場合、それらが挿入されなければなりません/更新/参照整合性制約を維持するために、非常に具体的で明白ではない順序で削除されます。場合によっては、循環依存関係を解決するためにシェルオブジェクトを挿入し、その外部キーを更新する必要がある場合もあります。削除されたオブジェクトを参照するために使用されたオブジェクトは、最初に更新された関係を持たなければならないので、削除は最後に行わなければなりません。

2グループ操作とテーブルアクセス:データベースのデッドロックを回避し、バッチ書込みを最適に使用できます。

3 - IDによる更新/削除を一貫して指示します。これは構成可能であり、潜在的なデータベースデッドロックを回避します。

もし、EclipseLinkが、アプリケーションがやることを盲目的に書いたのであれば、あなた自身でこれをすべて管理する必要があります。私はあなたが本当にこれをしたいと思うかどうか本当に疑問です。本当に必要な場合は、flush()を使用できます。

+0

申し訳ありませんが、私はそれを信じていません。我々はJPAの実装ではなく、AIであると私たちは話していますか? 'EntityManager'呼び出しの流れは何とか尊重されなければなりません。さもなければ、私のトランザクションはすべて、順序付けられていない2つのコレクション、つまりtoPersistと' toDelete'で終わることができます。このコード行で「削除」と言うと、それはJPAプロバイダにとって何かを意味するはずです。私は正しい? – Osw

関連する問題