連載
» 2004年12月11日 00時00分 公開

O/Rマッピングの導入効果を測るHibernateで理解するO/Rマッピング(6)(3/3 ページ)

[山本大,株式会社クロノス]
前のページへ 1|2|3       

習得効率を向上させるネイティブSQLクエリ機能

 APIの習得に要する時間は、フレームワーク導入初期の開発効率に影響する問題です。HibernateではSessionやSessionFactory、Queryなどのインターフェイスを主に利用しますが、どれも非常にシンプルで理解しやすいインターフェイスです。しかし、「HQLという新しいクエリ言語を覚え直さなくてはいけない」という懸念はHibernate導入の腰を重くする理由になるでしょう。しかし、その懸念もHibernateが「ネイティブなSQLクエリ」を実行できるAPIを用意していることを知れば、幾分か晴れるのではないでしょうか。

 リレーショナルデータベースの操作に当たっては、SQLを利用するのが最も効率的で柔軟な手段です。O/Rマッピングが広く普及したとしても、開発者はパフォーマンスチューニングやデバッグのためにSQLを理解する必要があるといえます。ネイティブなSQLが使えるのであればAPIの習得にかかる期間を多少は減らすことができるでしょう。

 また、開発チームの要員を探すときに「HQLを使ったことのある開発者」を募集してもあまり集まらないかもしれませんが、「SQLを使ったことのある開発者」であれば、ほとんどの開発者が該当するはずです。HQLはSQLに非常によく似た言語ですので、Hibernateを利用していくうちにHQLの習得度も上がってくるでしょう。

 なお、HibernateがネイティブなSQLクエリを実行する機能を備えている理由は、習得効率に関する問題解決のためだけではありません。例えば、ネイティブなSQLを実行できる機能によってJDBCベースのアプリケーションから

Hibernateへの移行がよりスムーズに行えるでしょう。またSQLには「方言」が存在します。SQLの方言とはRDBMS製品ごとに独自に実装されたSQLセンテンスのことです。使用しているデータベースのSQL方言を利用してクエリを作成したい場合には、このSQLクエリを実行できる機能が役立ちます。

SQLベースのQueryを作成する

 SQLクエリは、Queryインターフェイスによって実行することができます。ネイティブなSQLを使う場合、Session.createSQLQuery()を使ってQueryインターフェイスのインスタンスを取得します(HQLの場合も、Session.createQuery()メソッドを使うことでQueryインターフェイスのインスタンス取得することができます)。

createSQLQuery("SQL文字列", "テーブル別名", 結果POJOクラス)

 テーブル別名(エイリアス名)は、POJOマップされたクラスとSQL文中のテーブルを対応付けるために記述する必要があります。{mem.*}は、すべてのカラムを取得するための省略形の表現です。

Query sqlQuery = session.createSQLQuery("select {mem.*} from Member {mem}", "mem",Member.class);
List list = sqlQuery.list();

 以下のサンプルで、ネイティブなSQLクエリを実行してみましょう。

public static void main(String[] args) throws HibernateException {
  Configuration config = new Configuration();
  config = config.configure(); // 設定の読み込み
  SessionFactory sessionfactory = config.buildSessionFactory();
  Session session = sessionfactory.openSession();
  Query sqlQuery = session.createSQLQuery(
    "select {mem.*} from member {mem}", "mem", Member.class);
  List list =sqlQuery.list();
  for (int i = 0; i < list.size(); i++) {
    Member member = (Member) list.get(i);
    WorkGroup group = member.getWorkGroup();
    System.out.println(
      member.getNo() + ":" 
      + member.getName() + ";group:" 
      + group.getGroupname());
  }
  session.close();
}
リスト2 ネイティブなSQLクエリの実行コード
画面5 ネイティブSQLクエリの実行結果 画面5 ネイティブSQLクエリの実行結果

個々のカラムを指定する

 個々のカラムを明示的に記述したい場合は、それぞれの「SQLカラム」に対して「POJOのプロパティー名」での別名を指定しなければなりません。

 これらのカラムのための別名は、「テーブル別名」によって修飾したプロパティーの名前です。where 句内のプロパティーでも別名を使う必要があること注意してください。

String sql = 
" select " +
"     mem.no as {mem.no}, " +
"     mem.name as {mem.name} ," +
"     mem.groupno as {mem.groupno} " + 
" from Member {mem}" +
" where {mem}.no = :no ";
List list = session.createSQLQuery(sql, "mem", Member.class)
    .setInteger("no",1)
    .list();
リスト3 個々のカラムを指定したSQLクエリの実行コード

 また上記のコードでは、QueryインターフェイスのsetInteger()を使ってInteger型のPreparedStatementを使用しています。QueryインターフェイスはHQLでも同じく利用できます。Queryインターフェイスには、Integer型のほかにもString型やLong型といった値が使用できるメソッドが備わっています。

複数クラスとテーブルのマッピングSQL

 Joinを使って複数のクラスとテーブルをマップさせたい場合は、String配列型でテーブル別名を記述し、Class配列型でPOJOクラスを指定することもできます。この場合、実行結果はObject配列のリスト(つまりFetchされていない状態)で返却されるため、オブジェクト配列型にキャストするコードを記述する必要があります。

Query sqlQuery = session.createSQLQuery(
" select " +
"    {mem.*}," +
"    {wg.*} " +
" from member {mem} join workgroup {wg} “ +
“ on {mem}.groupno = {wg}.groupno", 
new String[] { "mem","wg"},
new Class[] {Member.class,WorkGroup.class}
);
List list =sqlQuery.list();
for (int i = 0; i < list.size(); i++) {
  Object[] items = (Object[]) list.get(i);
  Member member = (Member)items[0];
  WorkGroup group = (WorkGroup)items[1];
  System.out.println(
    member.getNo() + ":" 
    + member.getName() + ";group:" 
    + group.getGroupname()
);
}
session.close();
リスト4 複数クラスとテーブルのマッピングSQLクエリの実行コード

まとめ

 Hibernateを使ってO/Rマッピングの紹介をしてきましたが、6回にわたった連載も今回で終了です。J2EEの世界ではCMPでのさまざまな教訓を経て、Hibernateのような「専門的なO/Rマッピングフレームワーク」が誕生し、確実に普及し始めています。この「専門的なO/Rマッピングフレームワーク」がJ2EEの世界に与えた影響は大きく、EJB 3.0やJDO 2.0といった新しい仕様にも、その影響が色濃く反映されています。

 さらには、EJB 3.0およびJDO 2.0の「オブジェクト永続化の仕様」を統合して、新しいオブジェクト永続化仕様を策定しようとする動きも表れました。このことでJ2EEの永続化に関する矛盾はかなり解消の方向へ向かい標準化が進むことで、今後ますますO/Rマッピングが広がっていくことでしょう(新しい永続化仕様の策定が「難産」であろうことは想像に難くありませんが)。

 また、J2SE 5.0のリリースがエンタープライズ・アプリケーションの世界にも大きな影響を与え始めています。当然O/Rマッピングの各製品や仕様でも、J2SE 5.0のアノテーションやメタデータ機能を取り込んで大きく進化することが計画されています。そういった意味でも、現在J2EEは大きな過渡期を迎えています。しかし、この混とんは決して先の暗いものではなく、より簡単でスマートなシステム開発が可能となることを目指したものです。

 そのような情勢の最中で、Hibernateの制作チームの中心人物であるGavin King氏がEJB 3.0エキスパートグループやJDO 2.0エキスパートグループに所属したことからも、Hibernateは今後現れるさまざまなO/Rマッピング仕様の手本となるフレームワークの1つだといえます。次の世代のシステム開発に乗り遅れないためにもO/Rマッピングの仕組みを自分のものにしてください。本連載がその一助となれば幸いです。連載にわたって拙文にお付き合いいただきありがとうございました。

筆者紹介

株式会社クロノス

山本 大(やまもと だい)

株式会社クロノスに勤務するITアーキテクト。甲南大学 経営学部 卒業。J2EE、.NETにこだわらずベストソリューションを提供できるマルチプラットフォームアーキテクトを目指す。『XMLマスター教科書 プロフェッショナル』(翔泳社)や雑誌などで執筆活動も行っている。


前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。