作成 2004/11/16
最近Hibernateを調べてるのですが、へぇそんなこともできるのか、と思ったことをちらっとメモります。
Hibernateはオブジェクト間(テーブル間)の関連をhbmファイルにマッピングすることができます。オブジェクトの関連を定義すると、以下のことをHibernate側でやってくれます。
MySQLでこんなITEM、ITEM_DETAILという親子関係をもつテーブルを作り、対応するhbmとクラスを作りました。
で、テストデータを入れるのにINSERT処理を実行します。
この時点で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)
以下の例はItemクラスを主キー(ITEM_ID)でひろってきているだけです。
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ゲーム]
更新処理をしてみます。ここでは、Itemクラスを主キー(ITEM_ID)でひろってきて、 子要素のItemDetailを1つだけ名前をかえてみます。
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しにいきます。以前こういうの(明細の中で変更したものだけを一括更新)を自作で作って苦労した記憶があるので、こういうのは便利かもなぁ、と思ったりしましたです。
ItemDetailの方を検索してもItemがひっぱってこられます(hbmで関連つけているので)。
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とか)、イマイチまだ分かりません。 そのうち調べよう。