10

次の注釈付き Hibernate エンティティ クラスがあります。

@Entity
public class Cat {
    @Column(name = "ID") @GeneratedValue(strategy = GenerationType.AUTO) @Id
    private Long id;

    @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<Kitten> kittens = new HashSet<Kitten>();

    public void setId(Long id) { this.id = id; }
    public Long getId() { return id; }
    public void setKittens(Set<Kitten> kittens) { this.kittens = kittens; }
    public Set<Kitten> getKittens() { return kittens; }
}

@Entity
public class Kitten {
    @Column(name = "ID") @GeneratedValue(strategy = GenerationType.AUTO) @Id
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Cat cat;

    public void setId(Long id) { this.id = id; }
    public Long getId() { return id; }
    public void setCat(Cat cat) { this.cat = cat; }
    public Cat getCat() { return cat; }
}

ここでの私の意図は、Cat と Kitten の間の双方向の 1 対多/多対 1 の関係であり、Kitten が「所有側」になります。

私がやりたいことは、新しい Cat を作成し、続いてその Cat を参照する新しい Kitten を作成したときに、私の Cat の子猫のセットに新しい Kitten が含まれている必要があることです。ただし、これは次のテストでは発生しません。

@Test
public void testAssociations()
{
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    Transaction tx = session.beginTransaction();

    Cat cat = new Cat();
    session.save(cat);

    Kitten kitten = new Kitten();
    kitten.setCat(cat);
    session.save(kitten);

    tx.commit();

    assertNotNull(kitten.getCat());
    assertEquals(cat.getId(), kitten.getCat().getId());
    assertTrue(cat.getKittens().size() == 1); // <-- ASSERTION FAILS
    assertEquals(kitten, new ArrayList<Kitten>(cat.getKittens()).get(0));
}

Cat を再クエリした後でも、Set はまだ空です。

// added before tx.commit() and assertions
cat = (Cat)session.get(Cat.class, cat.getId());

ここで Hibernate に期待しすぎていますか? それとも、コレクションを自分で管理するのは自分の負担ですか? (注釈)ドキュメントには、親オブジェクトに便利なaddTo*/メソッドを作成する必要があることは示されていません。removeFrom*

この関係でHibernateに期待することについて誰か教えてもらえますか? または、他に何もない場合は、ここで何が起こると予想すべきかを教えてくれる正しい Hibernate ドキュメントを教えてください。

親コレクションに子エンティティが自動的に含まれるようにするにはどうすればよいですか?

4

2 に答える 2

15

自動的に追加されません。自分で追加する必要があります。

私も直接電話しませんKitten.setCat()。これの典型的なパターンは、メソッドを次のCatように配置することです。

public void addKitten(Kitten kitten) {
  if (kittens == null) {
    kittens = new HashSet<Kitten>();
  }
  kittens.add(kitten);
  kitten.setCat(this);
}

そして、単に呼び出します:

cat.addKitten(kitten);
于 2010-05-27T13:07:38.877 に答える
4

双方向の関連付けを使用する場合は、「リンク」の両側を処理する必要があり、@ cletusが提案するように、そのために防御的なリンク管理方法を使用するのが非常に一般的です。Hibernate Coreのドキュメントから:

1.2.6。双方向リンクの動作

まず、Hibernateは通常のJavaセマンティクスに影響を与えないことに注意してください。一方向の例では、どのようにして人物とイベントの間にリンクを作成しましたか?Personのインスタンスのイベント参照のコレクションにEventのインスタンスを追加します。このリンクを双方向にしたい場合は、イベントのコレクションにPerson参照を追加して、反対側でも同じことを行う必要があります。この「両側のリンクを設定する」プロセスは、双方向リンクでは絶対に必要です。

多くの開発者は、防御的にプログラムし、リンク管理メソッドを作成して、両側を正しく設定します(たとえば、Personで)。

protected Set getEvents() {
    return events;
}

protected void setEvents(Set events) {
    this.events = events;
}

public void addToEvent(Event event) {
    this.getEvents().add(event);
    event.getParticipants().add(this);
}

public void removeFromEvent(Event event) {
    this.getEvents().remove(event);
    event.getParticipants().remove(this);
}

コレクションのgetメソッドとsetメソッドが保護されるようになりました。これにより、同じパッケージ内のクラスとサブクラスが引き続きメソッドにアクセスできるようになりますが、他のすべてのユーザーがコレクションを直接変更することはできなくなります。反対側のコレクションに対して手順を繰り返します。

その他の参考文献

于 2010-05-27T19:31:46.127 に答える