Hibernate 入門記 コレクションその4 set で composite-element

前回に引き続きセットと値型の組み合わせ.今回は

  • <composite-element> 要素

です.
これは,複数のプロパティを持つ値型のオブジェクトをマッピングするものです.以前「マッピング定義その7 component & dynamic-component 要素」で学習したコンポーネントみたいな感じですかね.
その <composite-element> 要素,属性はたった一つだけ.

class
値型のクラスを指定します.必須です.

そして,この <composite-element> 要素の内容には,おなじみの <property> 要素を記述します.これも楽勝ですね.
っていうか,これで終わりみたい.うーみゅ,あまりにも簡単すぎて手抜きしているみたいじゃないですか.


早速お試ししましょう(早っ).
またしても例題はモデルとCMですが,CMは企業と宣伝対象の製品を別のプロパティにします.
ということでテーブル定義はこんな感じ.

CREATE TABLE MODEL (
    ID INTEGER IDENTITY,
    NAME VARCHAR
)

CREATE TABLE CM (
    ID INTEGER IDENTITY,
    CORPORATION VARCHAR,
    PRODUCT VARCHAR,
    MODEL INTEGER
)

モデルの永続クラスは「コレクションその1 setone-to-many」と同じです.
モデルのマッピングファイル study/Model.hbm.xml<element> 要素を <composite-element> 要素に変更します.

<?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"/>
            <composite-element class="Cm">
                <property name="corporation" access="field"/>
                <property name="product" access="field"/>
            </composite-element>
        </set>
    </class>
</hibernate-mapping>

続いてCMの永続クラス.

package study;
import java.io.Serializable;
import net.sf.hibernate.CallbackException;
import net.sf.hibernate.Lifecycle;
import net.sf.hibernate.Session;

public class Cm implements Lifecycle {
    int id = -1;
    String corporation;
    String product;

    public Cm() {
    }
    public Cm(String corporation, String product) {
        this.corporation = corporation;
        this.product = product;
    }
    public String toString() {
        return corporation + ":" + product;
    }

    public void onLoad(Session s, Serializable id) {
        System.out.println("onLoad() : " + toString());
    }
    public boolean onSave(Session s) throws CallbackException {
        System.out.println("onSave() : " + toString());
        return false;
    }
    public boolean onUpdate(Session s) throws CallbackException {
        System.out.println("onUpdate() : " + toString());
        return false;
    }
    public boolean onDelete(Session s) throws CallbackException {
        System.out.println("onDelete() : " + toString());
        return false;
    }
}

こいつは値型なので本来は hashCode()equals(Object) をオーバーライドすべきですが,手抜きしてます.心より恥じる.
hibernate.cfg.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 Ebihara");
            yuri.cm.add(new Cm("アビバ", "パソコン教室"));
            yuri.cm.add(new Cm("ゼスプリ", "ゴールドキウイ"));
            session.save(yuri);

            Model sayo = new Model("Sayo Aizawa");
            sayo.cm.add(new Cm("am/pm", "お弁当"));
            sayo.cm.add(new Cm("マルイ", "水着"));
            session.save(sayo);

            Model yu = new Model("Yu Yamada");
            yu.cm.add(new Cm("カネボウ", "テスティモ"));
            yu.cm.add(new Cm("カネボウ", "アリィー"));
            yu.cm.add(new Cm("ボーダフォン", "携帯"));
            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();
        }
    }
}

モデルの名前を漢字で書くとキーワードになってしまい,見に来た人をがっかりさせることになるのでアルファベットに戻しました.
ということで,実行!!

 onSave() : Yuri Ebihara, [ゼスプリ:ゴールドキウイ, アビバ:パソコン教室]
 Hibernate: insert into Model (name, id) values (?, null)
 Hibernate: CALL IDENTITY()
 onSave() : Sayo Aizawa, [am/pm:お弁当, マルイ:水着]
 Hibernate: insert into Model (name, id) values (?, null)
 Hibernate: CALL IDENTITY()
 onSave() : Yu Yamada, [カネボウ:テスティモ, カネボウ:アリィー, ボーダフォン:携帯]
 Hibernate: insert into Model (name, id) values (?, null)
 Hibernate: CALL IDENTITY()
 Hibernate: insert into cm (model, corporation, product) values (?, ?, ?)
 Hibernate: select model0_.id as id, model0_.name as name from Model model0_
 Hibernate: select cm0_.corporation as corporat2___, cm0_.product as product__, cm0_.model as model__ from cm cm0_ where cm0_.model=?
 onLoad() : Yuri Ebihara, [アビバ:パソコン教室, ゼスプリ:ゴールドキウイ]
 Hibernate: select cm0_.corporation as corporat2___, cm0_.product as product__, cm0_.model as model__ from cm cm0_ where cm0_.model=?
 onLoad() : Sayo Aizawa, [マルイ:水着, am/pm:お弁当]
 Hibernate: select cm0_.corporation as corporat2___, cm0_.product as product__, cm0_.model as model__ from cm cm0_ where cm0_.model=?
 onLoad() : Yu Yamada, [ボーダフォン:携帯, カネボウ:テスティモ, カネボウ:アリィー]
 Yuri Ebihara, [アビバ:パソコン教室, ゼスプリ:ゴールドキウイ]
 Sayo Aizawa, [マルイ:水着, am/pm:お弁当]
 Yu Yamada, [ボーダフォン:携帯, カネボウ:テスティモ, カネボウ:アリィー]

ということで,またしても楽勝.
でも,今回は「心より恥じる」を1回だけ使ったので,りっぱな入門記です(違).


さて,これでセットは終了です.次回からはマップに挑みます.たぶん.