2012-02-06 8 views
0

で存続/マージ、私はBが同様にマージすることにしたい - ちょうどいつもので、私はBの操作を行うことはありません、操作A.上のBのオブジェクトAオブジェクトを介してアクセス可能ですが、可能であればその逆もできません。 AとBを共有し、同じ主キーフィールドは、つまり、Bの主キーフィールドには、私は最終的にINSERTクエリが正しい順序になっているポイントにそれを持っている、しかし、Aの主キーに対する外部キーですそれはクエリパラメータにIDを結合いないので、主キーが設定されていないとして、しかし、それはInsertNullViolationを投げています。誰かがBのような結合されたオブジェクトの主キーをバインドするためにEclipseLinkを取得する方法を知っていますか?EclipseLinkは私がAをマージするとき、私は2つのエンティティ、AとBを持って参加したオブジェクト

public class A { 
    ... 
    @Id 
    @Column(name = "A_ID") 
    @SequenceGenerator(...) 
    @GeneratedValue(...) 
    public Long getA_ID(); 

    @OneToOne(mappedBy = "a", targetEntity = B.class) 
    public B getB(); 
    ... 
} 

public class B { 
    ... 
    @Id 
    public Long getA_ID(); 

    @MapsId 
    @OneToOne(targetEntity = A.class) 
    @JoinColumn(name="A_ID") 
    public A getA(); 
    ... 
} 

上記のセットアップがBに主キーを設定していないので、InsertNullViolationは、このセットアップでも同じ問題を持っているB.

public class A { 
    ... 
    @Id 
    @Column(name = "A_ID") 
    @SequenceGenerator(...) 
    @GeneratedValue(...) 
    public Long getA_ID(); 

    @OneToOne(mappedBy = "a", targetEntity = B.class) 
    public B getB(); 
    ... 
} 

public class B { 
    ... 
    @Id 
    @OneToOne(targetEntity = A.class) 
    @JoinColumn(name="A_ID") 
    public A getA(); 
    ... 
} 

に挿入しようとしてスローされます。例外は次のとおりです。

バインドラインの最後の nullが、それは私がマージするためのやっているオブジェクトA を挿入したとき、それは以前にシーケンスから取得し、実際のIDでのEclipseLinkで記入する必要があることを
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("SOME_USER"."B"."A_ID") 

Error Code: 1400 
Call: INSERT INTO B (SOME_FIELD1, SOME_FIELD2, ..., A_ID) VALUES (?, ?, ..., ?) 
bind => [null, SOME_VALUE, ..., null] 
Query: InsertObjectQuery([email protected]) 

本質的に次のようになります。

public void merge(A objectA, B objectB) { 
    objectA.setB(objectB); 
    entitymanager.merge(objectA); 
} 
+0

エンティティの永続化に使用しているコードも表示できますか? – Chris

答えて

1

問題はあなたが双方向の関係を維持する必要がありますB.

にAを設定していないことのようです、あなたのためにこれを行う魔法はありません。

Aを作成してBを割り当てるときは、AをBに割り当てる必要があります。そうでなければ、それはnullであり、nullが挿入されます。はこのように、あなたの代わりにこれを実行する必要があります。

public void merge(A objectA, B objectB) { 
    A.setB(objectB); //so when you merge A it knows about the B objects 
    B.setA(objectA); //so B knows to look at the A object for it's key 
    entitymanager.merge(objectA); 
} 

をさらに、BのAを設定するときにも、あなたを確認し、この値を設定する必要がありますので、あなたの最初の例では、あなたはまた、Bでの重複A_IDフィールドを持っています最初に、それ以外のIDはnullになります持続している、あなたはA_IDを削除し、あなたの第二の例で行ったようにOneToOneに@Idを置くことによってこれを避けることができます。また、その後、外部キーの値がOneToOneから来る、OneToOneにA_IDで偽と真の更新可能な挿入/ =置くことができます。 A_IDとOneToOneの両方が同じ列をマップするためですが、複数の書込み可能マッピングエラーを取得

、あなたは偽=、更新/挿入し、それらの1をマークする必要があります。

を参照してください、 http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Primary_Keys_through_OneToOne_and_ManyToOne_Relationships

と、 http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Object_corruption.2C_one_side_of_the_relationship_is_not_updated_after_updating_the_other_side

+0

ありがとう、それは問題でした。私はマージが動作するようにBをAに設定する必要があると思っていました。 – Trisfall

1

how to do it with Hibernateのドキュメントはこちらです。それは標準のJPAなので、EclipseLinkでも同じことができるはずです。

あなたにマッピングされたOneToOne協会とBにA_IDを交換(および他の側にmappedByを使用)のいずれか、またはあなたがA_IDを維持するだけでなく、AにOneToOneの関連付けを追加し、@MapsIdでそれを注釈付き(そしてあなたもう一方の側でmappedByも使用してください)。

+0

両方の例を試してみましたが、例外が発生しました。主キーフィールド[B.A_ID]に – Trisfall

+0

の1つの非読み取り専用マッピングが定義されているはずです。 IDを非読み取り専用IDとしてマップしましたか? –

+0

'updateable = false、insertable = false'のいくつかを削除し、' @ MapsId'の例に従ったところ、例外はなくなりましたが、Aの前にBを挿入しようとしても失敗しました。 'mappedBy'の例がありますか?理想的には、getA()メソッドは呼び出されないため、BからAへの結合はありません。私はメソッド 'getB()'をAにしたいだけです。フィールドの代わりにメソッドに注釈を付けることもできます。これまでのご協力ありがとうございます。 – Trisfall

0

私はparent.setChildren(子供を)やっていても、em.persist(親)を行ってきたので、私はこのエラーを得ました。だから私はchild.setParent(親)を追加しなければならなかった。しかし、em.persist(子)も実行できるので、永続化しているエンティティに相対的です。簡潔にするために、両方のエンティティで関係を設定してみてください。

私は前の行に書いたことをしたときに、私の外来キーと矛盾する "ORA-02291"エラーが発生しました。私のテーブルのPKを設定するためのトリガがあり、私のエンティティで@SequenceGeneratorも使用していたためでした。これを解決するには、TRIGGERで、new.PK_TABLEがnullの場合、PKのみMYSEQUENCE.nexvalに設定できることを検証する必要がありました。

私は昨日からこの問題に悩まされていたので、これは同じ問題を抱えている人を助けてくれました。

関連する問題