2012-07-01 25 views
9

私は、Spring Data JPAと一緒にJPAのオブジェクト@Idとしてプリミティブ型を使用することで問題を発見しました。 私は親側でCascade.ALLと親子関係にあり、子は同時に親のFKであるPKを持っています。プリミティブ型ではなくJPA @Idのプリミティブオブジェクトラッパーを常に使用しますか?

class Parent { 
    @Id 
    private long id; 

    @OneToOne(mappedBy = "parent", cascade = ALL) 
    private Child child; 
} 

class Child { 
    @Id 
    @OneToOne 
    private Parent parent; 
} 

だから、私は実行すると:

... 
Parent parent = new Parent(); 
Child child = new Child(parent); 
parent.setChild(child); 
em.persist(parent) 
... 

すべてが正常に動作します。しかし、私は、エンティティを永続化するために春データJPAを使用したので、私が代わりに実行します。

parentRepository.save(parent); // instead of em.persist(parent); 

と、この1は、次の例外で失敗しました:問題は、(保存春データJPAということでした

Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Parent 

メソッドはエンティティが新しいかどうかをチェックし、新しい場合はem.persist()が使用されます。そうでない場合はem.merge()が使用されます。

ここに興味深い部分どのエンティティが新しいかどうか春をチェック:

getId(entity) == null; 

そして、私は@Idの型として長く使用されているため、もちろん、これは、偽だった、とデフォルト値私が長い間Longに変更したとき、すべてがSpring Data JPAでも動作します。

プリミティブ型ではなく、プリミティブ型(LongではなくLongなど)にオブジェクトラッパーを使用することをお勧めします。これを推奨される方法として記述している第三者のリソースは非常に良いでしょう。

+0

この情報をGoogleにお知らせいただきありがとうございます。 –

+0

[ハイバーネーションの主キー用のプリミティブまたはラッパー]の複製が可能です(http://stackoverflow.com/questions/3535791/primitive-or-wrapper-for-hibernate-primary-keys) – stevedbrown

答えて

12

私は、あなたが見ているケースのためにプリミティブではなくオブジェクト型を使用することをお勧めします。エンティティが新規であるか、プリミティブ識別子で事前に存在するかを区別する方法はありません。私は長年にわたって休止状態を使用してきました。私は常に識別子のためにオブジェクトを使用します。

+1

+1、絶対に同意 – Raman

0

私はオブジェクトタイプを使用します。 xmlマッピングでは、 "保存されていない値"属性を入れることができますが、私はこれに対するアノテーションへの直接変換はないと思います。その結果、オブジェクト型を使用する方が安全です。

ほとんどのプログラマは、識別子の "null"値がとにかく未保存を意味すると予想します。

関連する問題