O/Rマッピングは、従来の煩雑なデータベースに関する処理の記述をスマートにし、柔軟なアプリケーションの構築を可能にします。本連載ではオープンソースのO/Rマッピングフレームワーク「Hibernate」を用いてO/Rマッピングの基礎を解説します。そしてさらに、J2EEアプリケーションへの実践的な適用方法とそのメリットも紹介していきます。(編集局)
リレーショナルデータベースの特徴は、その名のとおりデータを「リレーショナル」に扱えることにあります。リレーショナルに扱えるデータとはID番号や名前などのキーとなるフィールドのデータを利用して、「結合」や「抽出」を行えるデータです。
O/Rマッピングフレームワークの良しあしを判断するうえで重要な点は、リレーショナルデータベースの強力な機能を殺さず、かつ扱いやすいAPI(アプリケーション・プログラミング・インターフェイス)を提供しているか否かという点です。今回はHibernateを使ったリレーショナルデータの表現方法を紹介します。
今回のサンプルでは、テーブルを以下のように作成します。WorkGroupの1レコードに複数のMemberレコードが所属するという「1対多」のリレーションを持つテーブル構成となっています。使用するテーブルのER図は以下のようになります。
また、テーブルは以下のように作成します。
列名 | データ型 | 主キー | Not Null |
---|---|---|---|
NO | INTEGER | ○ | ○ |
NAME | VARCHAR(10) | ||
GROUPNO | INTEGER | ||
表1 Memberテーブルの定義 |
列名 | データ型 | 主キー | Not Null |
---|---|---|---|
GROUPNO | INTEGER | ○ | ○ |
GROUPNAME | VARCHAR(10) | ||
表2 WorkGroupテーブルの定義 |
作成したテーブルには、サンプルとして以下のようなテストデータを登録しておきます。
NO | NAME | GROUPNO |
---|---|---|
1 | iwashita | 1 |
2 | kawazu | 1 |
3 | kawano | 2 |
4 | Uozaki | 1 |
5 | masuda | 1 |
6 | mitsuyoshi | 2 |
7 | taga | 1 |
8 | tanaka | 2 |
9 | tanizawa | 1 |
10 | yamamoto | 2 |
11 | ysohida | 1 |
表3 Memberテーブルのサンプルデータ |
GROUPNO | GROUPNAME |
---|---|
1 | tokyo |
2 | osaka |
表4 WorkGroupテーブルのサンプルデータ |
テーブルが用意できたらマッピングファイルおよび永続化のためのJavaコードを作成していきましょう。まずは、Memberテーブルに対応するマッピングファイルを記述しましょう。
リスト1 Member.hbm.xmlファイル | ||||
<?xml version="1.0" ?>
<property name="name" type="string" column="NAME" />
</class> |
ここで、リスト1の中のコメント部分に関して少し詳細に解説しておきます。
1. 主キーカラム |
<id name="no" column="NO" type="java.lang.Integer" > |
マッピングテーブルには主キーが必要です。Hibernateには永続化時に主キーの「値」を生成するためのIDジェネレータークラスが用意されています。サンプルでは「assigned」を使用しています。このIDジェネレーターは主キーの自動生成を行いません。よって、アプリケーション側で一意なIDを設定する必要があります。IDジェネレーターの一部を以下に紹介します。
名前 | 説明 |
---|---|
Increment | インクリメンタルなLong、Short、INT型のIDを生成します |
hilo | hi/loアルゴリズムを使用してIDを生成します |
uuid.hex | 128ビットのUUIDアルゴリズムを使用して文字列型のIDを生成しますuuid.string |
uuid.string | uuid.hexと同じアルゴリズムを使い、16けたのASCII文字でエンコードされたUUIDを生成します |
native | 使用するデータベースの機能に応じて、identity、sequence、またはhiloを選びます |
assigned | アプリケーションでIDを生成し、永続化される前にオブジェクトに割り当てる必要があります |
foreign | 1対1のリレーションが設定されているときに、関連先のオブジェクトのIDを使用します |
表5 IDジェネレーター |
このほかにも多くのIDジェネレーターが提供されています。詳しい使用方法などはHibernateのマニュアルを参照してください。
2. 「多対1」マッピングカラム |
<many-to-one name ="workGroup" column="GROUPNO" |
MemberテーブルからWorkGroupテーブルへのマッピングを表現するタグとして<many-to-one>タグを使用します。
データベース設計に堪能な方なら「1対多」のリレーションはよくご存じでしょうが、「多対1」という呼び方にはなじみがないかもしれません。オブジェクト指向での「1対多」のリレーションは、そのリレーションが発生する主体によって「1対多」と「多対1」の2つの側面でとらえることができます。
サンプルで使用しているリレーションを、Memberテーブルを主体としてリレーションを見てみると、Memberテーブルのデータ複数に対してWorkGroupテーブルのデータが1つ決まるため「多対1」ということになりmany-to-oneのリレーションが使用されます。
表6 Member表からWorkGroup表へのリレーション
|
続いて、WorkGroupテーブルに対応するマッピングファイルを記述します。
リスト2 WorkGroup.hbm.xmlファイル | ||
<?xml version="1.0" ?>
</class> |
WorkGroupテーブルからMemberテーブルへの「1対多」のリレーションでは、複数レコードを扱う必要があるためコレクション型の指定が必要です。このサンプルではjava.util.Setインターフェイス型を用いてマッピングします。サンプルで使用している<set>タグのほかにも<map> <list> <bag>などがあります。
<set name="memberSet" > |
次にJavaコードの中で使用する永続化クラスを作成します。これらのクラスは、EntityBeanの重厚なオブジェクトに対して、シンプルな普通のオブジェクトという意味を強調してPOJO(Plain Old Java Object)と呼ばれています。
リスト3 Memberクラスのコード |
package sample.entity; |
リスト4 WorkGroupクラスのコード |
package sample.entity; |
さて、準備が整ったのでサンプルを実行するJavaコードを記述していきましょう。
リスト5 サンプル実行Javaコード |
3package sample; |
プログラムを実行すると、以下のような出力情報がコンソールに表示されます。
Sessionインターフェイスのfind()メソッドに対して、SQLに似た文字列のクエリを指定することで検索結果が得られます。このクエリをHQL(Hibernate Query Language)と呼びます。このHQLによってWorkGroupにひも付くMemberのリストが得られました。この取得結果をイメージで表すと以下のようになります。
Copyright © ITmedia, Inc. All Rights Reserved.