0

そのため、EntityManager.merge を使用すると、OpenJPA (2.1.1) と Hibernate (3.3.1) の動作に大きな違いが見られます。次のクラスを検討してください。

@Entity(name = "ChoiceHolder")
@Table(name = "CHOICEHOLDER")
@Inheritance(strategy = InheritanceType.JOINED)
public class ChoiceHolder
    implements Equals, HashCode
{

    protected int id;
    protected String choice3;
    protected String choice4;

    @Id
    @Column(name = "ID", scale = 0)
    public int getId() {
        return id;
    }

    public void setId(int value) {
        this.id = value;
    }

    @Basic
    @Column(name = "CHOICE3", length = 255)
    public String getChoice3() {
        return choice3;
    }

    public void setChoice3(String value) {
        this.choice3 = value;
    }

    @Basic
    @Column(name = "CHOICE4", length = 255)
    public String getChoice4() {
        return choice4;
    }
}

そして、次のクライアント コードを検討してください (これは単なる SSCCE です。私の実際の使用例では、同じ ID でマージする 2 つの呼び出しは、2 つの個別のクライアント操作から受信したデータを反映します。ここで、ID は 2 つの操作間で同じになるように意図されています。 ):

ChoiceHolder holder1a = new ChoiceHolder();
holder1a.setId(1);
holder1a.setChoice3("foo");
ChoiceHolder holder1b = new ChoiceHolder();
holder1b.setId(1);
holder1b.setChoice4("bar");

EntityManager em1 = factory.createEntityManager();
em1.merge(holder1a);
em1.close();
EntityManager em2 = factory.createEntityManager();
em2.merge(holder1b);
em2.close();
EntityManager em1Find = factory.createEntityManager();
ChoiceHolder holder1result = em1Find.find(ChoiceHolder.class, 1);
em1find.close();

ChoiceHolder holder2a = new ChoiceHolder();
holder2a.setId(2);
holder2a.setChoice3("foo2");
ChoiceHolder holder2b = new ChoiceHolder();
holder2b.setId(2);
holder2b.setChoice4("bar2");

EntityManager em3 = factory.createEntityManager();
em3.merge(holder2a);
em3.merge(holder2b);
em3.close();
EntityManager em2Find = factory.createEntityManager();
ChoiceHolder holder2result = em2Find.find(ChoiceHolder.class, 2);
em2Find.close();

Hibernate を使用して上記のコードを実行するholder1resultと、choice3 に null があり、choice4 に "bar" があります。同様に、holder2resultchoice3 には null があり、choice4 には "bar2" があります。ただし、openJPA を使用して同じコードを実行すると、非常に異なる結果が得られますholder1result。choice3 と choice4 の両方が設定さem3.merge(holder2b)れており、ReportingSQLException で呼び出しが失敗します。これは、INSERT が Choiceholder の ID の主キー制約に違反しているためです。

重要な場合は、Hibernate の構成に使用しているプロパティ ファイルの関連ビットを次に示します。

hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.connection.driver_class=org.postgresql.Driver
hibernate.hbm2ddl.auto=create-drop
hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider
hibernate.jdbc.batch_size=0

これは、openJPA の構成に使用されている私の persistence.xml からの対応するビットです。

<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
<property name="openjpa.jdbc.DBDictionary" value="postgres"/>
<property name="openjpa.ConnectionDriverName" value="org.postgresql.Driver"/>
<property name="openjpa.jdbc.MappingDefaults" value="DeferConstraints=true,ForeignKeyDeleteAction=restrict,JoinForeignKeyDeleteAction=restrict"/>

私の特定のケースでは、Hibernate で見られる動作が必要です。ただし、私の環境 (Karaf 内) では、代わりに OpenJPA を使用する必要があります。探しているものと一致するように動作を変更するために OpenJPA に設定できるフラグはありますか?

これはJPAの恐ろしい悪用ですか?もしそうなら、私が使用すべき他のテクニック/呼び出しシーケンスはありますか?

前もって感謝します!

4

1 に答える 1

2

まあ、私はいくつかの部分的な答えを思いつきました - しかし、心配する必要がある副作用があるかどうかはわかりません.

問題 1 はchoice3正しく null にされないため、persistence.xml ファイルで を設定openjpa.DetachStateする必要がありました。all

EntityManager.flush問題 2 については、呼び出しの間に呼び出しを追加しmergeて問題を修正します。奇妙なことに、最初の呼び出しの前に呼び出しを追加するとmerge問題も修正されるflushため、EntityManager に何らかの状態が設定されていると思われますが、その理由はわかりません。

于 2013-02-06T14:17:57.137 に答える