Hibernate 入門記 コレクションその3 set で element

前回・前々回は永続クラス(エンティティ)への1対多・多対多関連を学習しましたが,今回からは値型への対多関連です.
まずは,1つのカラムからなる値型をマッピングするための

  • <element> 要素

です.これは例によって,<set> 要素の子として,<key> 要素に続けて記述します.
その属性は二つしかありません.いずれも必須です.

column
コレクションの要素となるカラム名を指定します.
type
コレクションの要素となる型を指定します.型というのはHibernate型と思われ.

ふむふむ.
ということは,<many-to-many> 要素のように「あっち」への外部キーを指定できないので,1体多関連しかマッピングできないということですよね.っていうか,値型の多対多関連というのがあり得ないのか? 値型のオブジェクトは共有できないことになっていますから,向こうから見るとこっちの多重度は1しかあり得ないわけですか.なるほど.
ともあれ,これだけです.もうお試しできそうです.


ということで実験開始.
面倒なんで,文字列で試しましょう.マンネリですが,モデルが登場するCMの名前をコレクションで扱ってみましょう.「コレクションその1 setone-to-many」と同じ題材です.
まずは例によってテーブルなんですが,「コレクションその1」と全く同じです.
次にモデルですが,永続クラスはやはり「コレクションその1」と全く同じで,マッピングファイル study/Model.hbm.xml が次のようになります.

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"
>
<hibernate-mapping auto-import="false" package="study">
    <class name="Model">
        <id name="id" access="field" unsaved-value="-1">
            <generator class="identity"/>
        </id>

        <property name="name" access="field"/>
        <set name="cm" access="field" cascade="all">
            <key column="model"/>
            <element column="name" type="string"/>
        </set>
    </class>
</hibernate-mapping>

<one-to-many> 要素が <element> 要素に変わっただけです.
次に hibernate.cfg.xml なんですが,Cm.hbm.xml の参照を削除します.
最後に実行用のクラス.

package study;
import java.util.Iterator;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.cfg.Configuration;

public class Main {
    public static void main(String[] args) {
        try {
            Configuration config = new Configuration();
            SessionFactory factory = config.configure().buildSessionFactory();

            Session session = factory.openSession();

            Model yuri = new Model("蛯原友里");
            yuri.cm.add("アビバ");
            yuri.cm.add("ゼスプリゴールドキウイ");
            session.save(yuri);

            Model sayo = new Model("相沢紗世");
            sayo.cm.add("am/pm");
            sayo.cm.add("マルイ");
            session.save(sayo);

            Model yu = new Model("山田優");
            yu.cm.add("テスティモ");
            yu.cm.add("アリィー");
            yu.cm.add("ボーダフォン");
            session.save(yu);

            session.flush();

            session = factory.openSession();
            Iterator it = session.find("from study.Model").iterator();
            while (it.hasNext()) {
                System.out.println(it.next());
            }
        }
        catch (Throwable e) {
            e.printStackTrace();
        }
    }
}

昨日今日とやけにボーダフォンのCMが流れていたので追加しました.ってそういうことじゃないですよね.
「コレクションその1」と違っているのは Cm クラスをnew して Setadd() していたのを,文字列を add() するようにしただけです.それだけ.
ともあれ,実行!!

 onSave() : 蛯原友里, [ゼスプリゴールドキウイ, アビバ]
 Hibernate: insert into Model (name, id) values (?, null)
 Hibernate: CALL IDENTITY()
 onSave() : 相沢紗世, [マルイ, am/pm]
 Hibernate: insert into Model (name, id) values (?, null)
 Hibernate: CALL IDENTITY()
 onSave() : 山田優, [テスティモ, ボーダフォン, アリィー]
 Hibernate: insert into Model (name, id) values (?, null)
 Hibernate: CALL IDENTITY()
 Hibernate: insert into cm (model, name) values (?, ?)
 Hibernate: select model0_.id as id, model0_.name as name from Model model0_
 Hibernate: select cm0_.name as name__, cm0_.model as model__ from cm cm0_ where cm0_.model=?
 onLoad() : 蛯原友里, [ゼスプリゴールドキウイ, アビバ]
 Hibernate: select cm0_.name as name__, cm0_.model as model__ from cm cm0_ where cm0_.model=?
 onLoad() : 相沢紗世, [マルイ, am/pm]
 Hibernate: select cm0_.name as name__, cm0_.model as model__ from cm cm0_ where cm0_.model=?
 onLoad() : 山田優, [テスティモ, ボーダフォン, アリィー]
 蛯原友里, [ゼスプリゴールドキウイ, アビバ]
 相沢紗世, [マルイ, am/pm]
 山田優, [テスティモ, ボーダフォン, アリィー]

楽勝っ!!
っていうか,まるで手抜きしたみたいに感じるのはなぜ?
はっ! 「無念だ」も「心より恥じる」も「ぐはぁっ」も使っていないからだ! そんなの入門記じゃないやいっ!
でも優ちゃんの誕生日(日記タイムゾーンではまだ07/05)だし,たまにはこんなのもありということにしよう.