hibernate的model配置文件如下:
<property name="name" type="string">
<column name="NAME" length="12" />
</property>
<set name="childs" inverse="true" cascade="all" lazy="false">
<key>
<column name="PARENT_ID" length="10" />
</key>
<one-to-many class="com.max.Child" />
</set>
其中的inverse="true"表示 ParentPO 本身不維護(hù)表之間的關(guān)系,而由相反的一方 child來維護(hù), CASCADE=“ALL”表示 無論是update,insert ,delete 都保持級(jí)連關(guān)系
lazy="true"表示初始化父親的時(shí)候不會(huì)把所有的兒子都從數(shù)據(jù)庫(kù)中l(wèi)oad進(jìn)來。
首先講講inverse=true作用: 這里關(guān)系是由兒子維護(hù)的,所以如果只是往父親里加入兒子,不給兒子設(shè)置父親的話session.save(parent),就不會(huì)保存兒子! 看這個(gè)例子:
- ChildPO child = new ChildPO();,
- ITxMgr tx = null;
- tx = HibernateTxMgr.beginTrans("Add a new relationships...");;
- session = (Session); tx.getSession();;
- parent = new ParentPO();;
- ChildPO child = new ChildPO();;
- ChildPO child2 = new ChildPO();;
- List list = new ArrayList();;
- list.add(child);;
- list.add(child2);;
- parent.setChildren(list);;
- session.save(parent);;
- session.flush();;
- System.out.println("dddddddddddddddddddddddddddddddddddddddddddddddddddddd"); ;
- ChildPO child3 = new ChildPO();;
- child3.setParent(parent);;
- session.save(child3);;
- session.flush();;
- System.out.println("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"); ;
- tx.endTrans();;
生成的SQL沒有變
- Hibernate: insert into PARENT (ID); values (default);
-
- Hibernate: insert into CHILD (PARENTID, ID); values (?, default);
-
- Hibernate: insert into CHILD (PARENTID, ID); values (?, default);
-
- dddddddddddddddddddddddddddddddddddddddddddddddddddddd
- Hibernate: insert into CHILD (PARENTID, ID); values (?, default);
- eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
數(shù)據(jù)庫(kù)中數(shù)據(jù)如下:(注意父子關(guān)系丟失了)
- ----------- -----------
- 74 -
- 75 -
- 76 45
- C:\Myapp\SQLLIB\BIN>db2 select * from parent
-
- ID
- -----------
- 45
為什么最后一個(gè)孩子的父親沒有丟失呢? 就在于child3.setParent(parent),因?yàn)殛P(guān)系是由孩子維護(hù)的,如果child不setParent,或者 new childPO(父親)的話 父子關(guān)系就丟失了,parent.setChildren(list)是沒有用的!
之所以用inverse=true是為了提高系統(tǒng)的性能,在沒有設(shè)置inverse=true的情況下同樣調(diào)用上面的代碼則生成的sql如下:
- Hibernate: insert into CHILD (PARENTID, ID); values (?, default);
-
- Hibernate: insert into CHILD (PARENTID, ID); values (?, default);
-
- Hibernate: update CHILD set PARENTID=? where ID=?
- dddddddddddddddddddddddddddddddddddddddddddddddddddddd
- Hibernate: insert into CHILD (PARENTID, ID); values (?, default);
- Hibernate: values IDENTITY_VAL_LOCAL();
此時(shí)系統(tǒng)明顯比原來多了一句Hibernate: update CHILD set PARENTID=? where ID=?針對(duì)每一個(gè)孩子都去更新父親的id明顯速度很慢,因?yàn)楦赣H有個(gè)孩子的集合,他無法知道哪個(gè)孩子的父親id已經(jīng)指向自己了,所以對(duì)于每一個(gè)孩子,都要更新父親id,而這個(gè)關(guān)系由孩子維護(hù)就好多了,每個(gè)孩子只有一個(gè)父親,只有設(shè)置過的才需要更新,所以顯然,這個(gè)父子關(guān)系由孩子來維護(hù)比較省力.減輕了數(shù)據(jù)庫(kù)的負(fù)擔(dān)。
在沒有 inverse=true 的情況下,父子兩邊都維護(hù)父子關(guān)系所以 只要有 parent.setchildren(),或者 child.setparent()兩者之一就可以了
對(duì)inverse=true的總結(jié):不用inverse=ture,對(duì)開發(fā)者來說寫代碼比較方便,但是程序執(zhí)行的效率比較低下,,用inverse=ture一定要注意,一定要對(duì)維護(hù)關(guān)系的一方進(jìn)行調(diào)用,否則會(huì)有意想不到的破壞力。