5

1つのエンティティを削除して、別のエンティティを作成する必要があります。

@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();
  }
}

em.flush()コメントを残すと、次のようになりますcom.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException(新しいオブジェクトと古いオブジェクトのキー値は同じです)

そのような異常な行動の理由は何でしょうか?

サーバー: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
4

2 に答える 2

6

その理由は、Eclipselinkのドキュメントに記載されているように、Eclipselinkがコミット中に操作の順序を変更するためである可能性があります。

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

この動作は、フラッシュするか(すでに知っているように)、またはEclipselinkの特別なパラメーターを設定することによって変更できます。

オブジェクトを削除して置換を挿入することにより、オブジェクトを一意の制約で置き換えることを余儀なくされた場合、削除操作の前に挿入操作が発生すると、制約違反が発生する可能性があります。この場合、setShouldPerformDeletesFirst挿入操作の前に呼び出して削除操作を実行してください。

于 2012-04-12T09:17:17.590 に答える
1

EclipseLinkは、コミット順序を維持および最適化して、次のことを行います。

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

2-グループ操作とテーブルアクセス:これにより、データベースのデッドロックが回避され、バッチ書き込みを最適に使用できるようになります。

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

EclipseLinkがアプリケーションが実行した順序で盲目的に記述した場合は、これらすべてを自分で管理する必要があります。私はあなたが本当にこれをしたいと思うだろうと本当に疑っています。本当に必要な場合は、flush()を使用できます。

于 2012-04-12T12:33:01.730 に答える