第6章 コレクションのマッピング
6.1. コレクションの永続化 リンクのコピーリンクがクリップボードにコピーされました!
リンクのコピーリンクがクリップボードにコピーされました!
永続的なコレクション型のフィールドがインターフェース型として 宣言される必要があります。例えば、
public class Product {
private String serialNumber;
private Set parts = new HashSet();
public Set getParts() { return parts; }
void setParts(Set parts) { this.parts = parts; }
public String getSerialNumber() { return serialNumber; }
void setSerialNumber(String sn) { serialNumber = sn; }
}
実際のインターフェースには
java.util.Set、 java.util.Collection、 java.util.List、 java.util.Map、 java.util.SortedSet、 java.util.SortedMap などがあります。または、任意のインターフェースが使えます。(ただし、「任意のインターフェース」を使用する場合は、 org.hibernate.usertype.UserCollectionType の実装クラスを作成する必要があります。)
HashSet のインスタンスを持つインスタンス変数がどのように初期化されるかに注目してみましょう。これは新たにインスタンス化された(永続化されていない)インスタンスのコレクション型プロパティを初期化する最適な方法です。persist()を呼び出すことで、インスタンスを永続化しようとしたとき、 Hibernate は HashSet を Hibernate 独自の Set の実装インスタンスに置き換えます。このため、次のようなエラーには注意が必要です。
Cat cat = new DomesticCat();
Cat kitten = new DomesticCat();
....
Set kittens = new HashSet();
kittens.add(kitten);
cat.setKittens(kittens);
session.persist(cat);
kittens = cat.getKittens(); // Okay, kittens collection is a Set
(HashSet) cat.getKittens(); // Error!
Hibernate により注入された永続性コレクションは、インターフェース型に応じて、
HashMap や HashSet、 TreeMap、TreeSet、ArrayList のように振舞います。
コレクションインスタンスは、値型として普通に動作します。永続化オブジェクトに参照されたときに自動的に永続化され、参照が外されると自動的に削除されます。ある永続化オブジェクトから別の永続化オブジェクトに渡された場合、その要素は現在のテーブルから別のテーブルに移動するかもしれません。2つのエンティティが同じコレクションインスタンスを共有してはいけません。リレーショナルモデルをベースにしているため、コレクション型のプロパティに null 値のセマンティクス をサポートしていません。つまり Hibernate は参照先のないコレクションと空のコレクションを区別しません。
普段使っている Java のコレクションと同じように、永続化コレクションを使ってください。しかし、 双方向関連の意味を理解するようにしてください(これは後ほど説明します)。