続・双方向で 1 対 1 関連の Lazy フェッチ
この前の続き.
da-yoshi さんが
また、CASCADEに関しては、自然キーを使っている関連については、外部キー制約を持つ方からCASCADEするようにすればうまく動くみたいです。ただ・・・普通制約がある方が「子」のような気がするので、基本的にCASCADEについては制限があると思った方がいいのかも・・・
と書いておられたので,ちょっと試してみました.
この前の例では,Test4 の主キー (id) に Test3 の主キー (id) への外部キー制約を付けていました.
普通,この向きに制約を付けると Test3 が親側で Test4 が子側という感じがしますよね.
まぁ,1 対 1 で,どっちとも 1..1 なんだから親も子もない気もしますけど.
ともあれ (JW),それを逆にして,Test4 を親側に見立てて cascade="all"
を付ければうまく動く??
そんなわけで (どんなわけで?),やってみました.
マッピングファイルは Test4 の <one-to-one>
を次のように変更.
<one-to-one name="test3" constrained="true" cascade="all"/>
そしてテストメソッドの冒頭を次のように変更.
Test3 test3 = new Test3(); test3.setName("TEST3"); Test4 test4 = new Test4(); test4.setName("TEST4"); test4.setTest3(test3); test3.setTest4(test4); session.save(test4); session.flush(); session.clear();
Session#save()
に渡しているのは test4 だけで,test3 は渡していません.
その結果.
Hibernate: insert into Test3 (version, name, id) values (?, ?, null) Hibernate: call identity() Hibernate: insert into Test4 (version, name, id) values (?, ?, ?) Hibernate: select test3x0_.id as id0_0_, test3x0_.version as version0_0_, test3x0_.name as name0_0_ from Test3 test3x0_ where test3x0_.id=? TEST3.ID:103 TEST3.NAME:TEST3 TEST3.VERSION:2006-02-02 03:02:11.688 TEST4.ID:103 Hibernate: select test4x0_.id as id1_0_, test4x0_.version as version1_0_, test4x0_.name as name1_0_ from Test4 test4x0_ where test4x0_.id=? TEST4.NAME:TEST4 TEST4.VERSION:2006-02-02 03:02:11.766 Hibernate: select test4x0_.id as id1_0_, test4x0_.version as version1_0_, test4x0_.name as name1_0_ from Test4 test4x0_ where test4x0_.id=? TEST4.ID:103 TEST4.NAME:TEST4 TEST4.VERSION:2006-02-02 03:02:11.766 TEST3.ID:103 Hibernate: select test3x0_.id as id0_0_, test3x0_.version as version0_0_, test3x0_.name as name0_0_ from Test3 test3x0_ where test3x0_.id=? TEST3.NAME:TEST3 TEST3.VERSION:2006-02-02 03:02:11.688
おおぉぉぉ...
キレイに動きますね.ちょっとびっくり.
ちなみに SQL は手で整形してます>某巨大掲示板の 64 さん
どうやら,Session#save()
に渡されたオブジェクトに constrained="true"
な <one-to-one>
関連があると,関連先を先に INSERT しにいっちゃうみたいですね.
この前の場合だと,Test3 を INSERT する前に Test4 を INSERT しようとして,その前に Test3 を INSERT しようとするんだけどもう永続化しつつあるから無視して,でも Test4 を INSERT しにいっても Test3 がまだ INSERT されてないから外部キー制約違反で残念な思いをすることに.
上のようにすると,Test4 をINSERT するまえに Test3 を先に INSERT しようとして,その前に Test4 を INSERT しようとするんだけどもう永続化しつつあるから無視して Test3 が INSERT されて,その後で Test4 が INSERT されておっけー! みたいな.
でもなんか気持ち悪いなぁ.
個人的には cascade="all"
なんか外して Dao で頑張ればいいんじゃないかと思ったり.
public class Test3DaoImpl implements Test3Dao { public void save(Test3 test3) { Session session = sessionFactory.getSession(); session.save(test3); session.save(test3.getTest4()); } }
みたいな.