Hibernate メモ3

作成 2004/11/16

最近Hibernateを調べてるのですが、へぇそんなこともできるのか、と思ったことをちらっとメモります。

N:1マッピング

Hibernateはオブジェクト間(テーブル間)の関連をhbmファイルにマッピングすることができます。オブジェクトの関連を定義すると、以下のことをHibernate側でやってくれます。

関連には、one-to-one、many-to-manyなどいろいろな設定があるのですが、おそらく頻繁に使うだろうはN:1マッピング(one-to-manyおよびmany-to-one)でしょう。というわけで、N:1マッピングを試してみました。

準備

MySQLでこんなITEM、ITEM_DETAILという親子関係をもつテーブルを作り、対応するhbmとクラスを作りました。

で、テストデータを入れるのにINSERT処理を実行します。

Insert.java

この時点でDBには以下のデータが格納されています。

mysql> select * from item;
+---------+--------+
| ITEM_ID | NAME   |
+---------+--------+
|       1 | ゲーム |
+---------+--------+
1 row in set (0.00 sec)

mysql> select * from item_detail;
+--------+---------+-----------+
| SEQ_ID | ITEM_ID | NAME      |
+--------+---------+-----------+
|      1 |       1 | ドラクエ7 |
|      2 |       1 | ドラクエ8 |
|      3 |       1 | FF13      |
+--------+---------+-----------+
3 rows in set (0.00 sec)

検索です(N側から)

以下の例はItemクラスを主キー(ITEM_ID)でひろってきているだけです。

Select1.java

Item item = (Item)session.get(Item.class, new Integer(1));
System.out.println(item);

ちゃんと子要素もひろわれているようです。

hoge.Item@5fcf29,itemId=1,name=ゲーム[hoge.ItemDetail@ff2413,seqId=2,name=ドラクエ8,itemNameゲーム, hoge.ItemDetail@1d10a5c,seqId=1,name=ドラクエ7,itemNameゲーム, hoge.ItemDetail@9980d5,seqId=3,name=FF13,itemNameゲーム]

更新です(N側から)

更新処理をしてみます。ここでは、Itemクラスを主キー(ITEM_ID)でひろってきて、 子要素のItemDetailを1つだけ名前をかえてみます。

Update.java

Item item = (Item)session.get(Item.class, new Integer(1));
Set itemDetails = item.getItemDetails();
//適当に1つだけ名前変える
ItemDetail detail = (ItemDetail)itemDetails.iterator().next();
detail.setName(detail.getName()+"初回限定版");

実行すると、以下のようにレコードが一行更新されています。

mysql> select * from item_detail;
+--------+---------+---------------------+
| SEQ_ID | ITEM_ID | NAME                |
+--------+---------+---------------------+
|      1 |       1 | ドラクエ7初回限定版 |
|      2 |       1 | ドラクエ8           |
|      3 |       1 | FF13                |
+--------+---------+---------------------+
3 rows in set (0.00 sec)

ここでは、

ということが行われています。Hibernateは内部にダーティフラグをもっていて、変更のあったものだけUPDATEしにいきます。以前こういうの(明細の中で変更したものだけを一括更新)を自作で作って苦労した記憶があるので、こういうのは便利かもなぁ、と思ったりしましたです。

検索です(1側から)

ItemDetailの方を検索してもItemがひっぱってこられます(hbmで関連つけているので)。

Select2.java

List list = session.createQuery("from ItemDetail where name like '%ドラクエ%'").

LIKE条件でドラクエだけ検索しましたと。

hoge.ItemDetail@1171b26,seqId=1,name=ドラクエ7初回限定版,itemNameゲーム
hoge.ItemDetail@50988,seqId=2,name=ドラクエ8,itemNameゲーム

ちなみにここで発行されているSQLはSELECT3発。

Hibernate: select itemdetail0_.SEQ_ID as SEQ_ID, itemdetail0_.name as name, itemdetail0_.ITEM_ID as ITEM_ID from ITEM_DETAIL itemdetail0_ where (name like '%ドラクエ%' )
Hibernate: select item0_.ITEM_ID as ITEM_ID0_, item0_.name as name0_ from ITEM item0_ where item0_.ITEM_ID=?
Hibernate: select itemdetail0_.ITEM_ID as ITEM_ID__, itemdetail0_.SEQ_ID as SEQ_ID__, itemdetail0_.SEQ_ID as SEQ_ID0_, itemdetail0_.name as name0_, itemdetail0_.ITEM_ID as ITEM_ID0_ from ITEM_DETAIL itemdetail0_ where itemdetail0_.ITEM_ID=?

あれー?JOINじゃないなぁ?ItemDetailのフィールドクラスにしちゃダメなのか何か設定があるのか? JOINまわりとコレクションまわり(listとかidbugとか)、イマイチまだ分かりません。 そのうち調べよう。

参考

Hibernate in Action


BACK | TOP