冬眠は、子のコレクションに子供を追加していない多くのものに注釈を付けました
-
05-10-2019 - |
質問
次の注釈付きHibernate Entityクラスがあります。
@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; }
}
ここでの私の意図は、猫と子猫の間の双方向の1対多/多くの関係であり、子猫は「所有側」です。
私が起こりたいのは、私が新しい猫を作ってから、猫を参照する新しい子猫が続くときです。 私の猫の子猫のセットには、新しい子猫が含まれている必要があります. 。しかし、これ 起こらない 次のテストで:
@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));
}
猫を再び追いかけた後でも、セットはまだ空です:
// added before tx.commit() and assertions
cat = (Cat)session.get(Cat.class, cat.getId());
ここで冬眠からあまりにも多くのことを期待していますか?それとも、自分でコレクションを管理する負担はありますか? (注釈)ドキュメント 私が利便性を創造する必要があることを示すものではありません addTo*
/removeFrom*
親オブジェクトのメソッド。
誰かが私の期待がこの関係で冬眠からどうあるべきかについて私を啓発してくれませんか?または、他に何もない場合は、ここで何が起こるかを教えてくれる正しい冬眠文書を教えてください。
親コレクションに子エンティティを自動的に含めるために何をする必要がありますか?
解決
自動的に追加しません。自分で追加する必要があります。
私は直接電話しません Kitten.setCat()
また。これの典型的なパターンは、 Cat
お気に入り:
public void addKitten(Kitten kitten) {
if (kittens == null) {
kittens = new HashSet<Kitten>();
}
kittens.add(kitten);
kitten.setCat(this);
}
そして、単に電話してください:
cat.addKitten(kitten);
他のヒント
双方向の関連付けを操作する場合、「リンク」の両側を処理する必要があり、 @cletusが示唆するように、そのために防御リンク管理方法を使用することが非常に一般的です。 Hibernate Coreドキュメントから:
1.2.6。双方向リンクの動作
まず、Hibernateは通常のJavaセマンティクスに影響しないことに留意してください。単方向の例で、人とイベントの間のリンクをどのように作成しましたか?イベント参照のコレクション、人のインスタンスにイベントのインスタンスを追加します。このリンクを双方向にしたい場合は、イベントでコレクションへの人の参照を追加することで、反対側で同じことをする必要があります。 「両側にリンクを設定する」というこのプロセスは、双方向リンクで絶対に必要です。
多くの開発者は守備的にプログラムし、リンク管理方法を作成して、両側を正しく設定します(たとえば、直接)。
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およびセットメソッドが現在保護されています。これにより、同じパッケージとサブクラスのクラスがメソッドにアクセスすることができますが、他のすべての人がコレクションを直接変更するのを防ぎます。反対側のコレクションの手順を繰り返します。
その他の参照
- 1.2.6。双方向リンクの動作 (これはより明白です)
- 6.3.2。双方向協会
- 第21章、例:親/子
- 冬眠によるJavaの持続性