1.3.4. 値のコレクション

1.3.4. 値のコレクション

値型オブジェクトのコレクションを Person エンティティへ追加します。 E メールアドレスを格納したいのですが、 String 型を使っているので、コレクションは再び Set です:

private Set emailAddresses = new HashSet();

public Set getEmailAddresses() {
    return emailAddresses;
}

public void setEmailAddresses(Set emailAddresses) {
    this.emailAddresses = emailAddresses;
}

この Set のマッピングです:

<set name="emailAddresses" table="PERSON_EMAIL_ADDR">
    <key column="PERSON_ID"/>
    <element type="string" column="EMAIL_ADDR"/>
</set>

前のマッピングと比べて違うのは element の部分ですが、 Hibernate にこのコレクションが他のエンティティへの参照を含まず、 String 型の要素のコレクションを含むことを教えます(小文字の名前 (string) は Hibernate のマッピング型またはコンバータであるということです)。繰り返しますが、set 要素の table 属性は、コレクションのためのテーブル名を指定します。 key 要素はコレクションテーブルの外部キーカラム名を定義します。 element 要素の column 属性は String の値が実際に格納されるカラムの名前を定義します。

更新したスキーマを見てください:

_____________        __________________
 |             |      |                  |       _____________
 |   EVENTS    |      |   PERSON_EVENT   |      |             |       ___________________
 |_____________|      |__________________|      |    PERSON   |      |                   |
 |             |      |                  |      |_____________|      | PERSON_EMAIL_ADDR |
 | *EVENT_ID   | <--> | *EVENT_ID        |      |             |      |___________________|
 |  EVENT_DATE |      | *PERSON_ID       | <--> | *PERSON_ID  | <--> |  *PERSON_ID       |
 |  TITLE      |      |__________________|      |  AGE        |      |  *EMAIL_ADDR      |
 |_____________|                                |  FIRSTNAME  |      |___________________|
                                                |  LASTNAME   |
                                                |_____________|
 

コレクションテーブルの主キーは、実際は両方のカラムを使った複合キーであることがわかります。これは人ごとに E メールアドレスが重複できないということで、 Java の set に要求されるセマンティクスそのものです。

以前人とイベントを関連づけたときと全く同じように、今や試しにコレクションに要素を追加することができるようになりました。 両方とも Java では同じコードです。

private void addEmailToPerson(Long personId, String emailAddress) {

    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();

    Person aPerson = (Person) session.load(Person.class, personId);

    // The getEmailAddresses() might trigger a lazy load of the collection
    aPerson.getEmailAddresses().add(emailAddress);

    session.getTransaction().commit();
}

今回、コレクションの初期化に fetch クエリを使用しませんでした。そのため、 getter メソッドの呼び出しによってコレクションを初期化するための SELECT が実行されるので、コレクションに要素を追加できます。 SQL のログを監視して、即時フェッチを使って最適化してください。