2012-03-02 11 views
37

託児リファレンス(外部キー):JPA @OneToMany - >親 - 私はこのような何かがある場合は私が子供Entites IR からParentEntitiesを参照について質問があり

Parent.java:

@Entity(name ="Parent") 
public class Parent { 
    @Id 
    @Generate..... 
    @Column 
    private int id; 

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent") 
    private Set<Child> children; 

    simple ... getter and setter ... 
} 

をそしてChild.javaは:

@Entity(name ="Child") 
public class Child{ 
    @Id 
    @Generate.... 
    @Column 
    private int id; 

    @ManyToOne 
    private Parent parent; 

    ... simple getter an setter 
} 

次の表は、作成しようとしている。

Parent: 
    int id 

Child: 
    int id 
    int parent_id (foreign key: parent.id) 

これまでのところ、永遠にうまくいきました。しかし、JavaからこのReferenceを使用する場合は、このようなことができると思います。データベースでこれにつながる

@Transactional 
public void test() { 
    Parent parent = new Parent(); 

    Child child = new Child(); 
    Set<Child> children = new HashSet<Child>(); 
    children.add(child); 

    parent.setChildren(children); 
    entityManager.persist(parent); 
    } 

Parent: 
    id 
    100 

Child 
    id  paren_id 
    101 100 

しかし、ケースをないthatsの、あなたが明示的に持っているが、私は、フレームワークは、おそらくによって行うことができると思うだろう、子供(の親を設定しました自体)。

のでいただきましたが、実際にデータベースにこのです:私は子供の親を設定していない

Parent: 
    id 
    100 

Child 
    id  paren_id 
    101 (null) 

原因。だから私の質問:

私は本当にsthをする必要がありますか?このような?

Parent.java:

... 
setChildren(Set<Child> children) { 
    for (Child child : children) { 
    child.setParent.(this); 
    } 

    this.children = children; 
} 
... 

編集:

は速い回答によると、私はリファレンス所有エンティティに@JoinColumnを使用することで、この問題を解決することができました。例を上から取ると、私はsthしました。このような:

Parent.java:

@Entity(name ="Parent") 
    public class Parent { 
     @Id 
     @Generate..... 
     @Column 
     private int id; 

     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
     @JoinColumn(name= "paren_id") 
     private Set<Child> children; 

     simple ... getter and setter ... 
    } 

そしてChild.java:

@Transactional 
public void test() { 
    Parent parent = new Parent(); 

    Child child = new Child(); 
    Set<Child> children = new HashSet<Child>(); 
    children.add(child); 

    parent.setChildren(children); 
    entityManager.persist(parent); 
    } 

リファレンスが正しくによって設定されます。今、私たちはこれを行う場合

@Entity(name ="Child") 
public class Child{ 
    @Id 
    @Generate.... 
    @Column 
    private int id; 

    ... simple getter an setter 
} 

親:

Parent: 
    id 
    100 

Child 
    id  paren_id 
    101 100 

ありがとうございました。

+0

**子エンティティに親を持っていましたか?親がなければ、エラーが発生します(_StaleStateException:バッチ更新は、update [0]から予期しない行数を返しました;実際の行数:0; expected:1_)。注釈のない親を追加すると、エラーも表示されます(マッピングエラー)。子の親フィールドに@manytooneを設定すると、保存時にエラーが発生します(_ORA-00904: "REPORT_REPORT_ID":недопустимыйидентификатор_)。私のfkとidのIDはreport_idという名前だが、report_report_idがどこに来るのか分からない。 – Erlan

+0

(EclipseLink JPA実装の使用) @Column(name = "paren_id")プライベートlong parenIdが必要であることは注目に値する。このwotの仕事のためのあなたの子供のマッピング。 – AfterWorkGuinness

答えて

12

私は本当にsthをしなければなりませんか?このような?

これは戦略の1つです。

双方向関係では、関係の「所有」側と「非所有側」があります。あなたのケースの所有側がChildにあるので、永続化するためにそこに関係を設定する必要があります。所有側は通常@JoinColumnを指定した場所によって決まりますが、その注釈を使用しているようには見えませんので、ParentアノテーションでmappedByを使用したことから推測される可能性があります。

read a lot more about this hereとすることができます。

3

はい、そうです。 JPAはエンティティグラフの一貫性に注意しません。特に、双方向関係の所有者側に設定する必要があります(あなたの場合はChildの親属性に設定します)。

JPA 2。「1」と「多くのことを保証するために、それはランタイムの関係 - 例えばの一貫性を維持 する責任を負うアプリケーションであること

注意、 :0仕様が、これは言葉を次のように言われています双方向の 関係の側は、アプリケーション が実行時に関係を更新するとき、互いに一致しています。

1

上記のような単純なオブジェクトグラフを維持しながら、問題が発生しました。 H2で動かすと全てうまくいくが、私たちがMySQLに対して走ったとき、子テーブル(@JoinColumnアノテーションで定義されている)の "paren_id"は生成された親のidでポピュレートされていなかったDB内に外部キー制約がある-null列。

私たちは、このような例外を取得したい:

org.hibernate.exception.GenericJDBCException:フィールド「paren_id」は、このに遭遇するかもしれない他の誰のためにデフォルト値

を持っていないか、何をによると、(名前=「paren_id」偽= NULL可能)

@JoinColumnを

0

は私が正しくあなたを取得していた場合:我々は最終的に我々はそれが仕事を得るために@JoinColumnに別の属性を持っていたことがわかりましたEntityManager、もしあなたはそれが子供たちを永続させるべきであることを "彼に伝え"なければならないトランザクションの挿入命令を管理したい。そしてあなたはそれをしていないので、 "彼は"何を維持するか分からないが、あなたの親の子リストは空ではないので、 "彼"は正しいが、格納された値はnullです。

だからあなたのような何かを検討する必要があります。あなたはここで、親オブジェクトで何をしたい、その後コミットしないと、これはあまりにも似たようなケースのために働く必要があり

... begin, etc 
em.persist(child) 
em.persist(parent) 

を。

1

まだそうであるようです。親Entityでは、コードの他の場所で子/親関係を設定するためのコードの繰り返しを避けるために、

@PrePersist 
private void prePersist() { 
    children.forEach(c -> c.setParent(this)); 
} 

のようなものを持つことができます。

+0

!!素敵な男私は2週間alomostをつづけた。私はクライアントからjsonを送信しようとし、オブジェクトを@ springの@RequestBodyを使用してdbに保存しようとしました 私は自分の関係(親に設定された親は私には意味がない)を管理したくない – WRDev

+0

!!!更新!!! @PrePersistに関するリンク(@EntityListenerで管理できる) see - https://www.concretepage.com/java/jpa/jpa-entitylisteners-example-with-callbacks-prepersist-postpersist-postload-preupdate-postupdate -preremove-postremove – WRDev

関連する問題