めざましテレビ

今日の早耳ムスメ臼田あさ美ちゃーん,お題は「バリエーション豊富!! 最新ファーアイテム」.
まこたんからのコメント.

あさみちゃん!!やっぱりロングだったよ〜可愛い!

うそーん,あれって自毛なの? いつのまにそんなに??
っていうか,あり得ないって!! いくらなんでも伸びるの速すぎ.
そんなわけで (どんなわけで?),あさ美ちゃんの日記を調べたら...

7時くらいに撮影が終わって、明日からの仕事は髪の毛をロングヘアーでやることになったのでエクステンションを付けに美容室に行きました〜☆

やっぱりエクステじゃん.だめだなぁ>まこたん
ともあれ (JW),久々にあさ美ちゃんの着回しが充実.モデル顔もチラホラ,コンパクトにまとめた髪型もお似合いで満足度高し.
意外とキャスケットも似合ってるし.
でもでも,あさ美ちゃんにしては棒読みっぽいしゃべり方なのはどうしたのでしょうか?
麗菜ちゃんの真似? (^^;

Prolog 写経記 その 56 max/2

(ほぼ) 毎日淡々と Prolog を写経します.元ネタはこちら.

Prologユーティリティライブラリ

Prologユーティリティライブラリ

今日は max/2 を写経します.

解説

max(Numlist, Max) は数のリスト Numlist 中の最大値を返すか,あるいは MaxNumlist 中で最大の数かどうかを調べる.

ふむ.

モード

max(+, ?).

ふむふむ.

定義

では,こいつの定義を写経しませう.

max([X], X) :-
	!.
max([X | List], X) :-
	max(List, Max),
	X > Max, !.
max([_ | List], Max) :-
	max(List, Max), !.

ふむふむふむ.
リストの要素が一つだけならそれが最大値.
リストの先頭の要素が残りの要素からなるリストの最大値よりも大きければそれが最大値.
そうでなければリストの 2 番目以降の要素からなるリストの最大値が全体の最大値.
らじゃあ.

注記

max/2Numlist が空リストの場合や,その要素が数でない場合は失敗する.max/2 をアトムのリストに適用するには,アルファベット比較演算子 age (3 章参照) を > の代わりに用いるとよい.

ふむふむふむふむ.

では使用例を写経しませう.

2 ?- max([255, 713, 23, 521, 4], X).

X = 713 

Yes
3 ?- max([255, 713, 23, 521, 4], 255).

No

ふむふむふむふむふむ.


この定義,結果が正しいのは分かるのですがあまり効率的には見えませんね.
気に入らないのは,リストの先頭の要素が最大値でない場合に 2 番目の節と 3 番目の節で全く同じ再帰呼び出しを行うこと.
そんなの,明らかに
無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄無駄ぁぁぁぁぁぁぁぁぁぁ〜〜〜〜〜〜〜〜〜〜
ですから!! 残念!!!!


そんなわけで (どんなわけで?),再帰呼び出しを一回だけで済ませることにしましょう.
再帰呼び出しで2番目以降の要素中の最大値が先頭の要素よりも小さければ,先頭の要素が最大値に決まってるったら決まってます.
なので,

max([X], X) :-
	!.
max([X | List], Max) :-
	max(List, Max1),
	X =< Max1, !,
	Max = Max1.
max([X | _], X) :-
	!.

ってことになりました.
2 番目の節で

max([X | List], Max) :-
	max(List, Max),
	X =< Max, !.

としないでちょっと回りくどいことをしているのは,第 2 引数にリストの最大値と異なる具体的な数値を渡された場合に 3 番目の節へ進んでしまうのを防ぐため.
ともあれ (JW),例をお試し.

7 ?- max([255, 713, 23, 521, 4], X).

X = 713 

Yes
8 ?- max([255, 713, 23, 521, 4], 255).

No

いい感じ♪


Prolog 写経記 その 57 max/3

(ほぼ) 毎日淡々と Prolog を写経します.元ネタはこちら.

Prologユーティリティライブラリ

Prologユーティリティライブラリ

続けて max/3 を写経します.

解説

max(Numlist, Max) は数のリスト Numlist 中の最大値を返すか,あるいは MaxNumlist 中で最大の数かどうかを調べる.

ふむ.

モード

max(+, +, ?).

ふむふむ.

定義

では,こいつの定義を写経しませう.

max(X, Y, X) :-
	X >= Y, !.
max(X, Y, Y) :-
	Y > X, !.

ふむふむふむ.
そのまんま,ですね.

注記

max/3 は比較対象が数でないとき失敗する.max/3 をアトムに適用するには,アルファベット比較演算子 age,agt (3 章参照) をそれぞれ >=,> の代わりに用いるとよい.

ふむふむふむふむ.

では使用例を写経しませう.

10 ?- max(100, 77, M).

M = 100 

Yes
11 ?- max(-13.9, 13.9, -13.9).

No

ふむふむふむふむふむ.
特にどうという事もなく.


Re: hibernateを利用してはいけない5つのシチュエーション

「執拗につっこみ」と言われてもなんのその,関心を持ったことは日記に書くのだ (苦笑).
今日は

シチュエーション2 Torque等のCriteria系になれている場合

hibernateのCriteriaはおまけ程度です(公式ドキュメントにもそう書いてある)。
ちょっと複雑になると対処できません(Join一つとってもver2のころはaddJoinという直感的な物があったようですが、ver3のJoinは何?ま、関連を削除した時点で利用できませんが)。
Torqueでは非常に簡単にできたのに・・・と泣くことになりますので、hibernateの使用は避けましょう。

について.
この前も書いたように,自分は「Torque 等の Criteria 系になれている場合」に該当しないわけですが (っていうか Torque は遊んだことすらない),ちょっと気になる点がいくつか (いくつも?) あるのです.


まずは公式ドキュメントって?? リファレンスのこと??
どこに「おまけ程度」って書いてあるんだろう??
たしかに Hibernate 2.x では

Hibernate now features an intuitive, extensible criteria query API. For now, this API is less powerful and than the more mature HQL query facilities. In particular, criteria queries do not support projection or aggregation.

と,HQL より見劣りするということが書いてありますが,それのこと?
でもでも,元記事の著者さんって 3.x を使ってるみたいなんですが,そっちには

Hibernate features an intuitive, extensible criteria query API.

としか書いてないんですけどねぇ.
まぁいいや.


続いて「ver2のころはaddJoinという直感的な物があった」というところ.
そんなのあったっけ? 入門記で使った記憶はないような気のせいが...
とりあえず,2.1.x の JavaDoc では見あたりませんね.2.0.x にはあったのでしょうか?
ともあれ (JW),3.x の結合は 2.1.x とは大きく変わっていないようです.それなのに「ver3のJoinは何?」って何?
そんなわけで (どんなわけで?),Hibernate の Criteria を軽くまとめてみるテスト.
サンプルは例によって ModelMagazine で,多対 1 の関連があります♪


まずは普通に Model を取得してみましょう.

		Criteria criteria = session.createCriteria(Model.class);
		List<Model> l = criteria.list();
		for (Model model : l) {
			System.out.println(model);
		}

珍しく Tiger 使ってたりして (苦笑).
ともあれ (JW),ModeltoString()

	public String toString() {
		return firstName + " " + lastName + "(" + magazine.getName() + ")";
	}

となっていて,関連先の Magazine を参照します.
この実行結果.

Hibernate: select 
               this_.id as id0_, 
               this_.firstName as firstName1_0_, 
               this_.lastName as lastName1_0_, 
               this_.magazine as magazine1_0_ 
           from 
               Model this_
Hibernate: select 
               magazine0_.id as id0_, 
               magazine0_.name as name0_0_ 
           from 
               Magazine magazine0_ 
           where magazine0_.id=?
Yuri Ebihara(CanCam)
Naoko Tokuzawa(CanCam)
Maki Nishiyama(CanCam)
Hibernate: select 
               magazine0_.id as id0_, 
               magazine0_.name as name0_0_ 
           from 
               Magazine magazine0_ 
           where magazine0_.id=?
Yumi Sakurai(JJ)

Magazine は遅延ロードされていることが分かります.


そこで,Model を取得する際に Magazine も結合して取得したいとします.
いろいろなやり方があるのですが,手っ取り早いところではマッピングファイルで指定するとか.

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

		<property name="firstName"/>
		<property name="lastName"/>
		<many-to-one name="magazine" fetch="join"/>
	</class>
</hibernate-mapping>

<many-to-one> 要素の fetch 属性で "join" を指定します.
その場合の結果.

Hibernate: select 
               this_.id as id1_, 
               this_.firstName as firstName1_1_, 
               this_.lastName as lastName1_1_, 
               this_.magazine as magazine1_1_, 
               magazine2_.id as id0_, 
               magazine2_.name as name0_0_ 
           from 
               Model this_ 
                   left outer join Magazine magazine2_ on this_.magazine=magazine2_.id
Yuri Ebihara(CanCam)
Naoko Tokuzawa(CanCam)
Maki Nishiyama(CanCam)
Yumi Sakurai(JJ)

外部結合により,Model の取得時に Magazine が一気に取得されていることが分かります.
fetch 属性の指定は Criteria の他,Session#get()などで永続オブジェクトを取得する際や遅延初期化の際に有効になりますが,HQL では完全に無視されるので注意が必要です.


え? これじゃ Criteria でやってるって言わない?
そうかも (笑).
それに,マッピングファイルの指定とは違う方法で結合したい場合もあるでしょう.
そんな場合は,Criteria で明示的に結合させることもできます.
その場合もいくつかやり方がありますが,その一つはこんな感じ.

		Criteria criteria = session.createCriteria(Model.class);
		criteria.setFetchMode("magazine", FetchMode.JOIN);
		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

関連 magazine を結合することを明示的に指定しています.
ちなみに Hibernate 2.x では FetchMode.EAGER でしたが,3.x では FetchMode.JOIN がオススメっぽい.
結合させる場合は setResultTransformer()Criteria.DISTINCT_ROOT_ENTRY の指定をお約束にするのがオススメです.
今回の場合,多対 1 の多の側 (Model) に 1 の側 (Magazine) を結合しているので指定しなくても全然構わないのですけどね.逆の場合は常に指定した方がよいかと.
ともあれ (JW),その結果.

Hibernate: select 
               this_.id as id1_, 
               this_.firstName as firstName1_1_, 
               this_.lastName as lastName1_1_, 
               this_.magazine as magazine1_1_, 
               magazine2_.id as id0_, 
               magazine2_.name as name0_0_ 
           from 
               Model this_ 
                   left outer join Magazine magazine2_ on this_.magazine=magazine2_.id
Yuri Ebihara(CanCam)
Naoko Tokuzawa(CanCam)
Maki Nishiyama(CanCam)
Yumi Sakurai(JJ)

バッチリ.
ちなみに,マッピングファイルの fetch 属性は外してあります.


え? 単にフェッチするだけじゃなくて,問い合わせ条件で使いたい?
そんな場合もいくつかやり方がありますが,ここでは Criteria#createCriteria() を使います.基本となる Criteria から子の Criteria を作るのです.
「ver3のJoinは何?」ってこのことかな? でもでも,これって 2.x から変わっていないんですが.入門記でも使ったしね.
ともあれ (JW),CanCam 専属モデルだけを問い合せてみましょう.

		Criteria criteria = session.createCriteria(Model.class);
		Criteria magazineCriteria = criteria.createCriteria("magazine");
		magazineCriteria.add(Restrictions.eq("name", "CanCam"));

Hibernate 2.x では Expression#eq() とかでしたが,3.x では Restrictions#eq() なんかに変わっています.でも違いはその程度.
ともあれ (JW),その結果.

Hibernate: select 
               this_.id as id1_, 
               this_.firstName as firstName1_1_, 
               this_.lastName as lastName1_1_, 
               this_.magazine as magazine1_1_, 
               magazine1_.id as id0_, 
               magazine1_.name as name0_0_ 
           from 
               Model this_ 
                   inner join Magazine magazine1_ on this_.magazine=magazine1_.id 
           where 
               magazine1_.name=?
Yuri Ebihara(CanCam)
Naoko Tokuzawa(CanCam)
Maki Nishiyama(CanCam)

バッチリ.


え? 雑誌毎の専属モデルの人数を数えたい?
ふっふっふ.
ご安心ください.Hibernate 2.x ではサポートされていなかった Criteria の集合関数が 3.x ではサポートされてますよっ♪
某巨大掲示板の 271 さんも喜んでるに違いない.

		Criteria criteria = session.createCriteria(Model.class);
		criteria.setProjection(
			Projections.projectionList()
				.add(Projections.groupProperty("magazine.name"))
				.add(Projections.rowCount()));
		criteria.createAlias("magazine", "magazine");
		List<Object[]> l = criteria.list();
		for (Object[] row : l) {
			System.out.println(row[0] + " : " + row[1]);
		}

Projections#groupProperty() を指定するとそれで GROUP BY されるようです.
Projections#rowCount() が COUNT(*) みたいな.
その結果.

Hibernate: select 
               magazine1_.name as y0_, 
               count(*) as y1_ 
           from 
               Model this_ 
                   inner join Magazine magazine1_ on this_.magazine=magazine1_.id 
           group by 
               magazine1_.name
CanCam : 3
JJ : 1

いいねぇ♪ (昔懐かしいアコム風で)


え? 結果が Object[] なんて許せない?
ふっふっふ.
そんな場合は結果を Map にしてもらうこともできます.

		Criteria criteria = session.createCriteria(Model.class);
		criteria.setProjection(
			Projections.projectionList()
				.add(Projections.alias(Projections.groupProperty("magazine.name"), "magazine"))
				.add(Projections.alias(Projections.rowCount(), "count")));
		criteria.createAlias("magazine", "magazine");
		criteria.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
		List<Map<String, Object>> l = criteria.list();
		for (Map<String, Object> map : l) {
			System.out.println(map.get("magazine") + " : " + map.get("count"));
		}

リファレンスでは Criteria#returnMaps() なんてメソッドがあるように書いてあったりしますが,これは 2.1.x ですでに @deprecated になっていて,3.x では無くなったメソッドです.
なので,Criteria.ALIAS_TO_ENTITY_MAP を使います.
エイリアスの指定がちょっと面倒かなぁ.
それから,GROUP BY が使えるなら HAVING も欲しくなると思うけど,サポートしてるのかなぁ?
ちょっと見あたらない... HQL にはあるのに.まぁいいや.
ともあれ (JW),結果.

Hibernate: select 
               magazine1_.name as y0_, 
               count(*) as y1_ 
           from 
               Model this_ 
                   inner join Magazine magazine1_ on this_.magazine=magazine1_.id 
           group by 
               magazine1_.name
CanCam : 3
JJ : 1

バッチリ.


え? 副問い合わせも使いたい?
ふっふっふ.
Hibernate 3.x では Criteria での副問い合わせもできるようになりましたよっ♪
そんなわけで,各雑誌で姓が一番小さいモデルを問い合せてみましょう.つまり,副 (相関) 問い合わせの中で集合関数を使います.

		DetachedCriteria subQuery = DetachedCriteria.forClass(Model.class, "model2");
		subQuery.setProjection(Property.forName("model2.lastName").min());
		subQuery.add(Restrictions.eqProperty("model.magazine", "model2.magazine"));

		Criteria criteria = session.createCriteria(Model.class, "model");
		criteria.createAlias("magazine", "magazine");
		criteria.add(Property.forName("lastName").eq(subQuery));

		List<Model> l = criteria.list();
		for (Model model : l) {
			System.out.println(model);
		}

最初に DetachedCriteria で副問い合わせを作って,それを親の問い合わせで使います.
その結果.

Hibernate: select 
               this_.id as id1_, 
               this_.firstName as firstName1_1_, 
               this_.lastName as lastName1_1_, 
               this_.magazine as magazine1_1_, 
               magazine1_.id as id0_, 
               magazine1_.name as name0_0_ 
           from 
               Model 
                   this_ inner join Magazine magazine1_ on this_.magazine=magazine1_.id 
           where 
               this_.lastName = (
                   select 
                       min(this0__.lastName) as y0_ 
                   from 
                       Model this0__ 
                   where 
                       this_.magazine=this0__.magazine
               )
Yuri Ebihara(CanCam)
Yumi Sakurai(JJ)

バッチリ!!


集合関数や副問い合わせなど,3.x になって Criteria もずいぶんと強化されてますね.
まぁ,自分は必要がなければ Criteria よりも HQL を使いたいということに変わりはありませんが.
だって,HQL の方が分かりやすいし.最後の例と同等の HQL は次の通り.

from 
    hoge.Model model 
        left outer join fetch model.magazine magazine 
where 
    model.lastName = (
        select 
            min(model2.lastName) 
        from 
            hoge.Model model2 
        where 
            model.magazine = model2.magazine
    )

おいらにはこっちの方が Criteria よりもずっと分かりやすいっす.
HQL は SQL の方言みたいなものだけど,結合の指定が SQL よりも楽なのがいいところ♪
これをマッピングファイルに書いておけばメンテもそんなに苦じゃないし,Fetch Join する/しないのようなチューニングもやりやすいし.
問い合わせ条件等を実行時に組み立てるなら Criteria の方がいいかもしれませんけどね.


ともあれ (JW),複雑なことは試していないのでアレですが,Hibernate の Criteria ってそんなに Torque の Criteria に見劣りするんでしょうか?
Torque の「Advanced Criteria Techniques」をみた感じだと,そんなに差があるようにも見えませんが...
っていうか,ぐぐってみた限りだと Torque の Criteria では外部結合ができないとか集合関数が使えないとか副問い合わせができないとか出てきました.どれも古い情報だったので (最近は誰も Torque について書いてない?),最新版ではこれらもサポートされているのかもしれませんが,もしそのままだったらむしろ Hibernate よりも見劣りする部分もあるのでは?


「直感的」でないという点については何とも言い難いのですが,一つだけ言わせてもらうと,「Torque ではこうだった」という考えに縛られていてはいけないのではないかと思います.
例えば Torque の JavaDocCriteria#addJoin() を見たところ,どうやらこの API は引数の文字列で任意の結合条件を指定できるようです.
一方,Hibernate の場合はマッピングファイルに関連が定義されているのが前提であるため,その関連を指定する形で結合を指示します.
これは Hibernate と Torque ではそもそそもの成り立ちが違うことが原因でしょう.
その違いを受け入れずに Torque 流のやり方を求めてもしょうがないのではないかと思います.
例えて言うなら,Java を使っているのに「COBOL ではこうだった...」とか「COBOL で簡単にできたことが...」なんてことを言ってる間は Java をマスターできないよね,みたいな.
あう,Prolog をやりながら,「変数を書き換えられたら楽なのにぃ」とついつい思ってしまうことがあるのは内緒だ.


最後に「関連を削除した時点で利用できませんが」ってことなんですが...
これは「シチュエーション1 表示層(ビュー)がHTMLでない場合」から繋がっているわけですが,「関連を削除した時点」で Hibernate を使うメリットはほとんど無くなっているというか,O/R Mapper をマッピングしないで使うってどうよ? みたいな.
まずはその使い方に疑問を感じてしかるべきではないのかなぁ.
まぁ,世の中にはいろいろな人がいるもんだと改めて思った次第.
そんなわけで (どんなわけで?),明日か明後日かともかく後日,シチュエーション 1 についても書いてみるかもしれません.


ところで,元記事の著者さん,忙しいのかなぁ?
反応がないというか更新が止まってますね...
シチュエーション 4 について有力な説が見つかりはしましたが本当にそうなのか,どんな条件でああいうことになっているのか,是非とも知りたいのですけどねぇ.


relax 105 november 2005

「2005-2006 F/W ファッション特別号」という事で,特集が「モデルの気持ち。」.
そんなわけで (どんなわけで?),もえちゃん,紗世ちゃん,えみちぃ,潤ちゃんといったモデル 11 名が表紙を飾っています.
でもでも,期待して買うとちょっとがっかりかも.
内容は一人 1 ページの大きなカットと,全員を 2 ページで紹介しているところに 1 カットずつあるだけ.表紙を合わせて一人 3 カット.
大きなカットも普段雑誌で見ている彼女たちより魅力的とは言い難い...
JJ モデルの黒木メイサちゃんのカットは結構いいかも.


この特集,女性誌のモデルだけじゃなくて,いろいろなモデルを取り上げています.
はじめの方には GUCCI の 06SS Men's Collection の舞台裏なんかも.あんまりたいしたことないけど.
中程には GUCCI の 05/06AW の服を着たモデルをなぜか鴨川シーワールドで撮影したものとか (笑).


ともあれ (JW),ちょっと肩すかしを喰らった感じ.無念だ.


CanCam 11 月号 エビちゃんベストセレクション 13

CanCam2005年11月号の蛯原友里ちゃん

CanCam から,お気に入りの蛯原友里ちゃんを紹介しようというこのコーナー.
今日はサマンサタバサデラックスとのタイアップ「Welcome to Lovely World!!」から P278 の友里ちゃん.
ちょっとおすまし気味の表情かな?
でもでも,ちょっと気取った感じの友里ちゃんも大好きなのだ.
そんなわけで (どんなわけで?),やっぱり CanCam 買うしか!!