お仕事スタイル

  • 黒いシルクのカットソー(JIL SANDER 03SS)
  • 黒いコットンのパンツ(BALENCIAGA 04SS)
  • 黒いスエード+ナイロン・メッシュのスニーカー(sergio rossi 04SS)

天気予報では雨が降っても大したことなさそうだったので普通に出かけたのですが,夕方から大降りじゃないですか.部分的とはいえスエードの靴を履いていっちゃいましたよ.心より無念だ.

Hibernate入門記 マッピング定義その9 Hibernate型他

今回は「5.2. Hibernate Types」です.以前「何それ?」って思ったHibernateの型についての解説ですね.
まずは「5.2.1. Entities and values」.なんでも,HibernateJavaのオブジェクトを「エンティティ」と「値型」の二つに分類するそうです.
エンティティは,他のエンティティからの参照にかかわらず存在するオブジェクトとのことです.通常のJavaオブジェクトは,他のオブジェクト等から参照されなくなった場合,ガベコレに回収されてしまいますが,エンティティはそうではないとか.これは物理的なJavaのオブジェクトとしての話ではなくて,論理的な永続オブジェクトとしての話でしょうね.
また,エンティティは明示的に保存または削除しなければいけないとのこと.オブジェクトデータベースの標準であるODMGでは,エントリポイントからたどることができるオブジェクトは暗黙的に永続化されることになっていますが,Hibernateのエンティティはそうではない,とのことです.ただし,カスケード削除は除く,と.ふむふむ.リファレンスに書いてあることそのままだな.心より恥じる.
ということで昔懐かしいODMG標準について書いてみるテスト.ODMGというのは(かつては) Object Database Management Group の略称で(現在は Object Data Management Group の略称です),オブジェクトデータベース管理システム略してODBMSの標準化を目指していた団体です.その界隈ではオブジェクト指向データベース管理システム略してOODBMSとは呼ばないので注意.ともあれ,OMGによるCORBAのデータベース版を目指していた団体といえば手っ取り早いでしょうか.ODMG標準は,CORBA IDLを拡張した ODL(Object Definition Language) で記述した永続オブジェクトを,様々なプログラミング言語マッピングするというような仕様でした.意図的にCORBAそっくりになってます.そしてJavaに対応したのは ODMG2.0 からだったと思いますが(うろ覚え),その特徴が到達可能性(reachability)による暗黙的な永続化.C++バインディングにはそんなものはなかったはずなので,ちょっとなんだかなぁと思ったような気が.あ,Smalltalkバインディングには最初からあったかも.
その到達可能性による暗黙的な永続化というのは,データベースのエントリポイントから参照をたどることのできるオブジェクトは片っ端から永続化する(ODBに保存する),というものです.参照をたどることができなくなれば回収されます(ODBから削除される).ですから,明示的に保存とか削除とかする必要はないのでした.どこかにつなげてあげればOK.ObjectStore PSE for Java なんかがこれをサポートしていたはずなので(ODMG準拠というわけではなかったかもしれませんが),遊んだことがある人も多いかもしれませんね.
ともあれ,HibernateのエンティティはODMG標準とは異なり,明示的に保存しないと永続化されない,ということです.そして明示的に削除しないといけない,と.らじゃ.その方が私の好みです.


一方の値型ですが,これはJavaのプリミティブ型やコレクション,そして前々回に学習したコンポーネント,その他の不変オブジェクトの総称らしいです.こちらはエンティティと異なり,到達可能性により暗黙的に永続化されたり削除されたりするとのこと.というより,エンティティの一部として永続化されたり削除されたりすると理解した方がよさげ.ってリファレンスにそう書いてあるわけですが.それでその,値型はエンティティと異なりID(識別姓)を持たないとのこと.それゆえ,複数のエンティティで値型のインスタンスを共有することはないらしいです.ふむふむ.
つまり,エンティティは(ある意味)参照型,値型は値型なんですね.そのまんまやんけ.参照型っていうのは,その存在自体で識別されます.いわゆるオブジェクトIDみたいなっていうかポインタっていうか,同一性と呼ばれるやつですね(とはいえ実際にはIDプロパティの値による識別性を持つので厳密には参照型とは呼べない感じ).一方の値型には同値性という概念が出てきて,値が同じならそれは同じものだよね!ってことになります.あの 1 と この 1 は同じとか,あの "EbiYuri" とこの "EbiYuri" は同じってことです.そしてJavaObject 型は同値性ではなく同一性に基づいた equals(Object)hashCode() を提供します.なので,前々回作ったコンポーネント(値型)であるところの Name クラスは,やはり equals(Object)hashCode() をオーバーライドすべきだったのです.心より恥じる.
ま,過ぎたことを気にしても仕方がありません.次行きますよ! 次,次!(エビちゃん風)


コレクションを除いたHibernate型(エンティティと値型ですね)は,null のセマンティクスをサポートするそうです.逆に言うとコレクションはサポートしないってことですか.そういえば,前々回に <dynamic-component> を学習したのですが,そこでは Map にマップされているカラムが全て null だった場合,空の Map ではなく,Map 型のプロパティ自体が null になるとか書いてありました.それは null のセマンティクスをサポートしているのとは違うのでしょうか? 少し謎です.詳しくは6章に進めばわかるのかな? 今はここまでにしておきます.心より恥じる.
それから,Hibernateでいうところの永続クラスとは,エンティティのことだそうです.例えばコンポーネントは永続化されますが,それを永続クラスとは呼ばないらしいです.ふむ.いいでしょう,覚えておきましょう.


なんか,今日は字が多くて黒っぽいなぁ.(^^; ま,気にせず次へ行きましょう.「5.2.2. Basic value types」です.
永続クラスで使用できる基本的な型がずら〜り.意外なものをピックアップすると...

localetimezonecurrency
Javaでの各クラス型のプロパティをVARCHARなど文字列型のカラムにマップしてくれるそうです.あまり使うとは思えませんが,意外なところでこってるんだなぁ,ということで.
class
これも Class 型のプロパティをやはりVARCHARなど文字列型のカラムにマップしてくれるそうです.あって困る訳じゃないけど,Java以外では使いようがないカラムになっちゃいますね... それってDBとしてどうよ?
serializable
プロパティ(が参照しているオブジェクト)をシリアライズしたものを,バイナリ型のカラムにマップしてくれるそうです.これまたJava以外では(略)

うーみゅ,たぶん使わないな.(^^;
それでですね,エンティティやコレクションのIDとしては,binaryblobclog 以外の基本型を使えるとのことです.らじゃ.


次は「5.2.3. Persistent enum types」です.ほほぅ,永続的な列挙型ですか.
Hibernateでは,いわゆる列挙型を扱うために

  • PersistentEnum

という interface を用意していて,こいつを implements することで,永続的な列挙型を用意できるそうです.列挙型は不変オブジェクトで,実際の値は(小さな)数値型とのこと.数値型との相互変換のために,次のメソッドを実装します.

    • toInt()
    • fromInt(int)

fromInt(int)static なメソッドです.楽勝っぽい.


ガンガン行きますよぉ.次は「5.2.4. Custom value types」です.
プロパティを標準的にサポートされるのとは異なる型のカラムにマッピングしたいとか,一つのプロパティを複数のカラムにマッピングしたいというような場合は,UserType または CompositeUserType という interfaceimplements したクラスを作ればいいとのことです.でも,コンポーネントとかあるし,滅多に使うことはないみたい.ということで... 次行きますよ! 次,次!(エビちゃん風)
で,「5.2.5. Any type mappings」なんですが,これは継承絡みみたい.くどいようですが,継承はスキップしまくっているので,ここでも当然スキップ♪ 心より恥じる.


ということで,お試ししましょう.もちろん列挙型に決まってます.モデルネタで列挙型といえば,血液型ですね.これでいってみましょう.
まずは前回までの雑誌に替えて,血液型のカラムを持つテーブルを用意します.

CREATE TABLE MODEL (
    ID INTEGER IDENTITY,
    FIRSTNAME VARCHAR,
    LASTNAME VARCHAR,
    BLOOD INTEGER
)

次に列挙型である血液型のクラス.

package study;
import net.sf.hibernate.PersistentEnum;

public class Blood implements PersistentEnum {
    public static final Blood A = new Blood(0);
    public static final Blood B = new Blood(1);
    public static final Blood O = new Blood(2);
    public static final Blood AB = new Blood(3);

    private static final String TEXT = new String { "A", "B", "O", "AB" };

    private final int code;
    private Blood(int code) {
        this.code = code;
    }
    public int toInt() {
        return code;
    }
    public static Blood fromInt(int code) {
        switch (code) {
            case 0 :
                return A;
            case 1 :
                return B;
            case 2 :
                return O;
            case 3 :
                return AB;
            default :
                throw new RuntimeException("Unknown Blood code");
        }
    }
    public String toString() {
        return TEXT[code];
    }
}

リファレンスからのパクリです... 心より恥じる.
これを使うように修正したモデルのクラス.

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

public class Model implements Lifecycle {
    int id = -1;
    Name name;
    Blood blood;

    public Model() {
    }
    public Model(String firstName, String lastName, Blood blood) {
        this.name = new Name(firstName, lastName);
        this.blood = blood;
    }
    public String toString() {
        return name + ", " + blood;
    }

    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;
    }
}

そしてマッピングファイル.

<?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>

        <component name="name" class="Name" access="field">
            <property name="firstName" access="field"/>
            <property name="lastName" access="field"/>
        </component>
        <property name="blood" access="field"/>
    </class>
</hibernate-mapping>

そして実行用のクラス.

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", Blood.O);
            session.save(yuri);

            Model sayo = new Model("Sayo", "Aizawa", Blood.AB);
            session.save(sayo);

            Model naoko = new Model("Naoko", "Tokuzawa", Blood.O);
            session.save(naoko);

            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();
        }
    }
}

へぇ〜,紗世ちゃんって獅子座のABなんだ.おいらと同じだ!\(^o^)/
そして実行!!

 onSave() : Yuri Ebihara, O
 Hibernate: insert into Model (firstName, lastName, blood, id) values (?, ?, ?, null)
 Hibernate: CALL IDENTITY()
 onSave() : Sayo Aizawa, AB
 Hibernate: insert into Model (firstName, lastName, blood, id) values (?, ?, ?, null)
 Hibernate: CALL IDENTITY()
 onSave() : Naoko Tokuzawa, O
 Hibernate: insert into Model (firstName, lastName, blood, id) values (?, ?, ?, null)
 Hibernate: CALL IDENTITY()
 Hibernate: select model0_.id as id, model0_.firstName as firstName, model0_.lastName as lastName, model0_.blood as blood from Model model0_
 onLoad() : Yuri Ebihara, O
 onLoad() : Sayo Aizawa, AB
 onLoad() : Naoko Tokuzawa, O
 Yuri Ebihara, O
 Sayo Aizawa, AB
 Naoko Tokuzawa, O

おっけー♪


ということで,「5.2. Hibernate Types」はお終いです.
この後は「5.3. SQL quoted identifiers」なのですが,テーブル名やカラム名を引用符で囲みたい場合はバッククォートを使えってだけなので,これも終了にします.
そして「5.4. Modular mapping files」はサブクラスのマッピングファイルは分割できるよってことなのですが,例によって継承関係はスキップなのです.
ということで... 「5. Basic O/R Mapping」終了です!!\(^o^)/
いやぁ,長かったなぁ.途中ずいぶんさぼりましたからねぇ.心より恥じる.
来週からは心を入れ替えて頑張る所存であります.たぶん...
次は「6. Collection Mapping」ですか.対多関連の登場ですね.挫折しないように頑張らねば.

「恋するハニカミ!」

三角デートの後編.ということで蛯原友里ちゃんの衣装は先週と同じ.
そして... ちゃんとしたセリフもなし.(ToT)
ところどころで声が聞こえた気はしますが... 無念だ.
時々ちらりと映る友里ちゃんは素敵なのですが,これではレポートになりません.プレミアに期待です〜.

「プレミアの巣窟」

蛯原友里ちゃんをたっぷりと堪能できるありがたい番組,今週もレポートです♪
今回の友里ちゃんの衣装は濃いめのベージュのワンピース.例によってウェストまわりがたっぷりと余ってます.これはやはり,友里ちゃんの細さにあう服が少ないせいなのか? それに茶のニーハイブーツ.この時期にブーツってちょっとびっくりな感じですが,ワンピースの丈が短めなのでブーツでバランスをってことでしょうか? せっかくなので脚を見せて欲しかった... 無念だ.
今になってみると,第一回放送時の衣装は露出度高めでサービス満点だったんですねぇ.
このところ,オープニングでは友里ちゃんの話題で楽しませてくれていたのですが,今回は久しぶりにゲストが登場ということで友里ちゃんネタはありませんでした.無念だ.いかんいかん.だんだん贅沢になってきてます.友里ちゃんがたくさん映って喋っているだけでも十分貴重だというのに.
ともあれ,最初のイベントをそつなく紹介して順調なスタート.そうかぁ,紅白に出演するとそれだけでトロフィーがもらえるんですね.ってこれはイベントとは関係ありませんが.
そして次のイベントは「ピーターパン」.ということでピーターパン役の中村美貴ちゃんという子がゲストで登場.うーん,やっぱりゲストが登場するとハニカミみたいになっちゃいますね... 主にゲストと天野っちの会話が主で,友里ちゃんの出番が減っちゃいます.さすがにハニカミよりは随分とましですが.
しかし,おかげで気づいたことがあります.以前(特にハニカミ)だと友里ちゃん,ちょっと油断して退屈そうな表情をしていることがちょこちょこあったのですが,今日はずっとにこやかな表情♪ いいっすねぇ.
続いてはチャゲ&飛鳥のツアーの紹介.

友里:今回のライブには「熱風」という名の,伝説のツアータイトルが付けられているそうなんです.
天野:な,何が伝説なんですか,それは.
友里:佐野さんから... お願いします!
天野:面倒くさくなったんじゃないのか?
友里:違いますよぉ!
佐野:こういうところ僕ですね.

あはは,委譲しちゃった?(^^; 別にそういうわけじゃなくて,最初から佐野アナの担当だったみたいなんですが,友里ちゃんがとっさに「佐野さんから...」って言っちゃったので天野っちに突っ込まれることになったみたいです.「違いますよぉ!」のセリフが可愛い♪
そして音楽が! 「Premiere Flush」の時間です! 今回も紫フレームのメガネ,チェーンはなしです.
出だしでちょっと躓いて「えっとぉ」で始まってしまいました (^^; が,どうにかイベントの紹介をして,恒例になりつつある二元中継もどきにちょっとした毒舌を交えてあっというまに「Premiere Flush」終了... 早すぎ (;_;)
っていうか,番組自体がそのままあっという間に終了... 早すぎ (;_;)
やはりゲストが登場すると満足度が下がってしまうようです.無念だ.

CanCam Style

すでに日付が変わって06/26(土)なんですが,ということは新宿伊勢丹蛯原友里ちゃんが一日店長として登場の日です.
生ユリを堪能するチャンスではあるのですが,そのためには「CanCam Style」というコーナーで一万円以上のお買い物をしなければなりません.まぁ,一万円はいいですよ.問題ありません.
しかしですねぇ,先着順なんで開店前から並ばないと無理でしょう? そして女の子の服を買わなきゃいけないわけですよ.ちょっとしんどいなぁ.
やはりパーティーの方の抽選に漏れたのが... 無念だ.
ということで,今回の生ユリは見送りです.心より恥じる.
バーニーズNYのセールが始まるので新宿には行くと思うのですけどね.天気が回復すれば.

CanCam 8月号

エビちゃんではなくて,徳澤直子ちゃんの話題.
今月はエビちゃんOLの1か月CDがお休みだったわけですが,かわりに「下着はど〜するの? めちゃモテOL7月の1か月CD」というコーナーがあります.
そこで1ショットだけ,徳澤直子ちゃんの下着姿が掲載されているのです.といっても女性誌なので全くエロくないんですが(苦笑)...
その下着がですね,ジョン・ガリアーノのジャーナルプリント(新聞柄)なんですよ.
それが普通のジャーナルプリントならもうちょっとエロくなりそうな感じなんですが,赤いハートもプリントされていて,それでキュートに見えるんですね.結構意外.
ちょっとチェックです♪
やべ,後半が始まっちゃう!

France 0 - 1 Greece

どひゃー,フランスが負けましたか.びっくりですねぇ.
インテルカラグーニスがいるというだけで少しだけギリシャを応援していたのですが,まさか勝つとは思ってもいませんでした.
でも,ギリシャってそんなに目立った選手いませんよねぇ? 攻守共に.みんなできっちり守って少ないチャンスを生かしたって事みたいですが,フランス相手じゃそれだって簡単なことでもないだろうし,ちょっと不思議でした.
っていうか単にジダンのできが悪かっただけですか? あまり「すげぇ!」ってのがなかったような.
ともあれ,ギリシャチェコになったら渋い試合になりそうだなぁ.(^^;
明日はスウェーデン−オランダですか.楽しみ♪