Hibernate 入門記 問い合わせ その4 order by,group by,副問い合わせ,フィルタ

今日はなんか,ゆりかもめで強い日差しを浴びすぎてぐったりしてしまいました.
頭も働かないし,結構睡魔に襲われ気味なのでお休みしようかとも思ったのですが,また休み癖が付いてしまいそうなので,老体に鞭打ち頑張るのだぁ〜.
そんなわけで (どんなわけで?),「11.9. The order by clause」へと進みます.SQL と同様に order by が使えるそうです.
前回と同じサンプルでお試し.

from study.Model order by model.age

その実行結果.

Jun Hasegawa(18)
Asami Usuda(19)
Karina null(20)
Yu Yamada(20)
Satoko Koizumi(23)
Yuri Ebihara(24)
Sayo Aizawa(26)

同じ ViVi に出ている潤ちゃんと紗世ちゃんが両端ですか.(^^;
どうでもいいけど降順も試しておきますか.

from 
    study.Model model 
order by 
    model.name.firstName desc, model.name.lastName desc

その実行結果.

Yuri Ebihara(24)
Yu Yamada(20)
Sayo Aizawa(26)
Satoko Koizumi(23)
Karina null(20)
Jun Hasegawa(18)
Asami Usuda(19)

永続オブジェクト自身でソートするとどうなるのでしょうか?

from 
    study.Model model 
order by 
    model

その実行結果.

Sayo Aizawa(26)
Yuri Ebihara(24)
Asami Usuda(19)
Yu Yamada(20)
Satoko Koizumi(23)
Jun Hasegawa(18)
Karina null(20)

その時のSQL

select 
    model0_.id as id, model0_.FIRST_NAME as FIRST_NAME, model0_.LAST_NAME as LAST_NAME, 
    model0_.age as age, model0_.magazine as magazine 
from 
    Model model0_ 
order by  
    model0_.id

なるほど,ID プロパティでソートされるんですね.
order by はこんなもんで十分でしょう.
次行きますよ! 次,次!!(エビちゃん風)


そんなわけで (どんなわけで?),次は「11.10. The group by clause」.
でも,集計関数の所でもう group by 使いましたから! 残念!!!!
でもでも,having が使えるらしいです.なのでお試し.

select 
    magazine.name, avg(model.age) 
from 
    study.Model model 
        inner join model.magazine magazine 
group by 
    magazine.name 
having 
    avg(model.age) > 20 
order by 
    2

その実行結果.

[CanCam, 21.0]
[Oggi, 23.0]

ふむ.order by 2 みたいなのも普通に使えますね.
ということで,group by および having もこんなもんでいいかな.
次行きますよ! 次,次!!(エビちゃん風)


そんなわけで (どんなわけで?),「11.11. Subqueries」です.
副問い合わせも使えるそうです.ただし,RDBMS がサポートしていれば.

from 
    study.Model model 
where 
    model.age > (
        select avg(model2.age) from study.Model model2
    )

その実行結果.

Sayo Aizawa(26)
Yuri Ebihara(24)
Satoko Koizumi(23)

ふむ.普通ですね.
次行きますよ! 次,次!!(エビちゃん風)


そんなわけで (どんなわけで?),次は「11.12. HQL examples」.
んー,スキップ.(^^;
困ったことがあれば参考にさせて頂くということで...
次行きますよ! 次,次!!(エビちゃん風)


そんなわけで (どんなわけで?),11章のラスト「11.13. Tips & Tricks」.
んー,これも例が載っているだけな感じだけど... Tricks に興味があるので軽く見てみますか.
HQL 中の名前付きパラメータの値を,JavaBeans を使って与えることが出来るそうです.
それには HibernateQuery を使います.
...
うーみゅ,自前の問い合わせクラスの名前も Query なのは大失敗!!
ともあれ (JW),その study.Query の問い合わせ部分を次のように修正.

            final List list = (List) template.process(new HibernateCallback() {
                public Object doProcess(Session session) throws Exception {
                    net.sf.hibernate.Query query = session
                            .createQuery("from study.Model model "
                                    + "where model.name.firstName = :firstName "
                                    + "and model.name.lastName = :lastName");
                    query.setProperties(new Name("Yuri", "Ebihara"));
                    return query.list();
                }
            });

その実行結果.

net.sf.hibernate.QueryException: 
    Not all named parameters have been set: [firstName, lastName] 
        [
            from study.Model model 
            where model.name.firstName = :firstName and model.name.lastName = :lastName
        ]

ぐはぁっ.何? 何だっていうわけ!?
しまった... Name クラスには getter がなかった...(ToT)
うーみゅ,Hibernate がフィールドでアクセスしてくれるのに甘えて getter/setter 書かずに済ませていたのが敗因ですか.やっぱり手抜きはいかんですね...
ということで,とりあえず getter のみ追加.Eclipse ありがとう!
実行!!

Yuri Ebihara(24)

よっしゃ!!


それから,永続オブジェクトがプロパティとして持つコレクションを対象に問い合わせをする,フィルタというものを使うことも出来るようです.
そんなわけで (どんなわけで?),問い合わせ用のクラスを次のように修正.

            final List list = (List) template.process(new HibernateCallback() {
                public Object doProcess(Session session) throws Exception {
                    Magazine cancam = (Magazine) session.load(Magazine.class,
                            new Integer(0));
                    return session.filter(cancam.model, "order by this.age");
                }
            });

まずは CanCam を取得して,専属モデルのコレクションを年齢で並べ替えています.
こいつを実行!!

Asami Usuda(19)
Yu Yamada(20)
Yuri Ebihara(24)

おおおおぉぉぉぉ...
やるなぁ,Hibernate
その時のSQL

Hibernate: select 
               magazine0_.id as id0_, magazine0_.name as name0_, 
               magazine0_.publisher as publisher0_ 
           from 
               Magazine magazine0_ 
           where 
               magazine0_.id=?
Hibernate: select 
               model0_.magazine as magazine__, model0_.id as id__, 
               model0_.magazine_index as magazine6___, model0_.id as id0_, 
               model0_.FIRST_NAME as FIRST_NAME0_, model0_.LAST_NAME as LAST_NAME0_, 
               model0_.age as age0_, model0_.magazine as magazine0_ 
           from 
               Model model0_ 
           where 
               model0_.magazine=?
Hibernate: select 
               this.id as id, this.FIRST_NAME as FIRST_NAME, this.LAST_NAME as LAST_NAME, 
               this.age as age, this.magazine as magazine 
           from 
               Model this 
           where 
               this.magazine = ? 
           order by  
               this.age

むむぅ?
最初の問い合わせは CanCam を取得するもの.これはよし.
次の問い合わせは CanCam の専属モデルを問い合わせするもの.Hibernate は普通こういう風に問い合わせするのでこれもよし.
そして次のは... order by が付いてます.これがフィルタにより作成された問い合わせですね.ふーん.
つまりフィルタというのは,メモリ上で HQL を適用してくれるわけではなくて,引数で渡した永続オブジェクトの持つコレクションを問い合わせるのに必要な SQL を作ってくれるっていう感じ? なぁんだ,ちょっとがっかり.
この場合だと,FROM 句と WHERE 句は Hibernate が作ってくれているので,その分だけ少しは楽... なんだろうか? やたらと SQL 発行されるくらいなら,一発ですむような HQL を自分で書いた方がいいんじゃないかと考えてしまいます.


今日は最初から最後まで駆け足で雑な入門記になってしまったような.
ちがうの、ゆりかもめでのぼせちゃったの。
まぁ言い訳ですが。©眞鍋かをり


そんなわけで (どんなわけで?),これで「11. HQL: The Hibernate Query Language」を終了とします.やれやれ.
次は... 「12. Criteria Queries」ですか.これもちょっとダルそうだなぁ... あ,でも量は少なめ.ちぇっ,
『はんぶんにしてくださぁぁぁぁぁい!!!!!』©眞鍋かをり
とセカチュってみたかったのにぃ.残念!!!!
ともあれ (JW),頑張りますよ.早く 14 章にたどり着いてパフォチュってみたいのだ!