首先以父子關係爲例:
<
對應生成的DDL drop table PARENT;
- drop table CHILD;
- create table PARENT (ID INTEGER not null generated by default as identity, primary key (ID););;
- create table CHILD (ID INTEGER not null generated by default as identity, PARENTID INTEGER, primary key (ID););;
- alter table CHILD add constraint FK3D1FCFC74B18345 foreign key (PARENTID); references PARENT;
drop table CHILD;
create table PARENT (ID INTEGER not null generated by default as identity, primary key (ID););;
create table CHILD (ID INTEGER not null generated by default as identity, PARENTID INTEGER, primary key (ID););;
alter table CHILD add constraint FK3D1FCFC74B18345 foreign key (PARENTID); references PARENT;
*大寫的部分inverse="true"表示 ParentPO 本身不維護表之間的關係!,而由想反的一方 children來維護,
*CASCADE=“ALL”表示 無論是update,insert ,delete 都保持幾連關係
*lazy="true"表示初始化父親的時候不會把所有的兒子都從數據庫中load進來。
下面先看一下幾個例子:
生成的SQL:
- Hibernate: insert into PARENT (ID); values (default);
- Hibernate: insert into CHILD (PARENTID, ID); values (?, default);
- Hibernate: insert into CHILD (PARENTID, ID); values (?, default);
Hibernate: insert into PARENT (ID); values (default);
Hibernate: insert into CHILD (PARENTID, ID); values (?, default);
Hibernate: insert into CHILD (PARENTID, ID); values (?, default);
結果 C:/Myapp/SQLLIB/BIN>db2 select * from child
- ID PARENTID
- ----------- -----------
- 71 44
- 72 44
- 73 44
- C:/Myapp/SQLLIB/BIN>db2 select * from parent
- ID
- -----------
- 44
ID PARENTID
----------- -----------
71 44
72 44
73 44
C:/Myapp/SQLLIB/BIN>db2 select * from parent
ID
-----------
44
注意之只有一句:session.save(parent);就把兩個兒子保存進了數據庫。
*首先講講inverse=true作用: 這裏關係是由兒子維護的,所以如果只是往父親里加入兒子,不給兒子設置父親的話session.save(parent),就不會保存兒子! 看這個例子:注意與例子1的對比
- *ChildPO child = new ChildPO(parent);---〉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();;
*ChildPO child = new ChildPO(parent);---〉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
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
*注意父子關係丟失了 C:/Myapp/SQLLIB/BIN>db2 select * from child
- ID PARENTID
- ----------- -----------
- 74 -
- 75 -
- 76 45
- C:/Myapp/SQLLIB/BIN>db2 select * from parent
- ID
- -----------
- 45
ID PARENTID
----------- -----------
74 -
75 -
76 45
C:/Myapp/SQLLIB/BIN>db2 select * from parent
ID
-----------
45
*爲什麼最後一個孩子的父親沒有丟失呢? 就在於child3.setParent(parent);,所以關係是由孩子維護的,如果child不setParent,或者 new childPO(父親)的話 父子關係就丟失了,parent.setChildren(list);是沒有用的!
*這裏就又引入了另外一個問題爲什麼要用inverse? 用了它維護關係起豈不是很麻煩?,這裏給出個例子給大家一個解釋:(關鍵原因在於性能)
下面這個例子和例子一完全一樣,所差的就是沒有用inverse=true
例子2:
- hibernate-mapping>
- <class name="com.etech.bm.po.ChildPO" table="CHILD">
- <id name="id" column="ID" type="integer">
- <generator class="identity"/>
- </id>
- <many-to-one name="parent" class="com.etech.bm.po.ParentPO" column="PARENTID"/>
- </class>
- <class name="com.etech.bm.po.ParentPO" table="PARENT">
- <id name="id" column="ID" type="integer">
- <generator class="identity"/>
- </id>
- <bag name="children" CASCADE=“ALL”>
- <key column="PARENTID"/>
- <one-to-many class="com.etech.bm.po.ChildPO"/>
- </bag>
- </class>
- </hibernate-mapping>
hibernate-mapping>
<class name="com.etech.bm.po.ChildPO" table="CHILD">
<id name="id" column="ID" type="integer">
<generator class="identity"/>
</id>
<many-to-one name="parent" class="com.etech.bm.po.ParentPO" column="PARENTID"/>
</class>
<class name="com.etech.bm.po.ParentPO" table="PARENT">
<id name="id" column="ID" type="integer">
<generator class="identity"/>
</id>
<bag name="children" CASCADE=“ALL”>
<key column="PARENTID"/>
<one-to-many class="com.etech.bm.po.ChildPO"/>
</bag>
</class>
</hibernate-mapping>
- drop table PARENT;
- drop table CHILD;
- create table PARENT (ID INTEGER not null generated by default as identity, primary key (ID););;
- create table CHILD (ID INTEGER not null generated by default as identity, PARENTID INTEGER, primary key (ID););;
- alter table CHILD add constraint FK3D1FCFC74B18345 foreign key (PARENTID); references PARENT;
drop table PARENT;
drop table CHILD;
create table PARENT (ID INTEGER not null generated by default as identity, primary key (ID););;
create table CHILD (ID INTEGER not null generated by default as identity, PARENTID INTEGER, primary key (ID););;
alter table CHILD add constraint FK3D1FCFC74B18345 foreign key (PARENTID); references PARENT;
- ITxMgr tx = null;
- tx = HibernateTxMgr.beginTrans("Add a new relationships...");;
- session = (Session); tx.getSession();;
- parent = new ParentPO();;
- ChildPO child = new ChildPO(parent);;
- ChildPO child2 = new ChildPO(parent);;
- 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();;
ITxMgr tx = null;
tx = HibernateTxMgr.beginTrans("Add a new relationships...");;
session = (Session); tx.getSession();;
parent = new ParentPO();;
ChildPO child = new ChildPO(parent);;
ChildPO child2 = new ChildPO(parent);;
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();;
hibernate 生成的sql Hibernate: insert into PARENT (ID) values (default)
- 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();
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();
結果 C:/Myapp/SQLLIB/BIN>db2 select * from parent
- ID
- -----------
- 46
- ID PARENTID
- ----------- -----------
- 77 46
- 78 46
- 79 46
ID
-----------
46
ID PARENTID
----------- -----------
77 46
78 46
79 46
明顯比原來多了一句Hibernate: update CHILD set PARENTID=? where ID=?針對每一個孩子都去更新父親的id明顯速度很慢,因爲父親有個孩子的集合,他無法知道哪個孩子的父親id已經指向自己了,所以對於每一個孩子,都要更新父親使他只想自己,而這個關係由孩子維護就好多了,每個孩子只有一個父親,只有設置過的才需要更新,所以顯然,這個父子關係由孩子來維護比較省力.減輕了數據庫的負擔
*現在我們再來看看在沒有 inverse=true 的條件下 ChildPO child = new ChildPO(parent)---〉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();;
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 生成的sql Hibernate: insert into PARENT (ID) values (default)
- 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();
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();
結果 C:/Myapp/SQLLIB/BIN>db2 select * from child
- ID PARENTID
- ----------- -----------
- 83 48
- 84 48
- 85 48
ID PARENTID
----------- -----------
83 48
84 48
85 48
C:/Myapp/SQLLIB/BIN>db2 select * from parent
- ID
- -----------
- 48
ID
-----------
48
*顯然在 沒有 inverse=true 的情況下,父子兩邊都維護父子關係所以 只要有 parent.setchildren(),或者 child.setparent()兩者之一就可以了
對inverse=true的總結:不用inverse=ture,對開發者來說寫代碼比較方便,但是程序執行的效率比較低下,,用inverse=ture一定要注意,一定要對維護關係的一方進行調用,否則會有意想不到的破壞力。