在我們實際項目中,多對多的情況也時長存在,比如最常見的就是系統管理的五張表,如下面的一個結構:

在本文學習hibernate多對多關聯映射的實驗中我簡單的寫幾個字段,達到學習目的即可。
1.多對多的關系表達
1.關系型數據庫(RDB)中的表達:

2.Java實體中的表達


3.orm配置文件中的表達:(注意每次添加了ORM映射文件都要加到主配置文件中)
User.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!-- 配置表與實體對象的關系 --> <!-- package屬性:填寫一個包名.在元素內部凡是需要書寫完整類名的屬性,可以直接寫簡答類名了. --> <hibernate-mapping package="cn.qlq.domain" > <!-- class元素: 配置實體與表的對應關系的 name: 完整類名 table:數據庫表名 --> <class name="User" table="sys_user" > <!-- id元素:配置主鍵映射的屬性 name: 填寫主鍵對應屬性名 column(可選): 填寫表中的主鍵列名.默認值:列名會默認使用屬性名 type(可選):填寫列(屬性)的類型.hibernate會自動檢測實體的屬性類型. 每個類型有三種填法: java類型|hibernate類型|數據庫類型 not-null(可選):配置該屬性(列)是否不能為空. 默認值:false length(可選):配置數據庫中列的長度. 默認值:使用數據庫類型的最大長度 --> <id name="user_id" > <!-- generator:主鍵生成策略 --> <!--identity : 主鍵自增.由數據庫來維護主鍵值.錄入時不需要指定主鍵. --> <generator class="native"></generator> </id> <!-- property元素:除id之外的普通屬性映射 name: 填寫屬性名 column(可選): 填寫列名 type(可選):填寫列(屬性)的類型.hibernate會自動檢測實體的屬性類型. 每個類型有三種填法: java類型|hibernate類型|數據庫類型 not-null(可選):配置該屬性(列)是否不能為空. 默認值:false length(可選):配置數據庫中列的長度. 默認值:使用數據庫類型的最大長度 --> <property name="User_name" length="20"/> <property name="user_state"/> <!-- 集合,多對多關系,在配置文件中配置 --> <!-- name:集合屬性名字 table:中間表名 --> <set name="roles" table="sys_user_role"> <!-- column:外鍵,別人引用我的外鍵列名 --> <key column="user_id" ></key> <!-- class:我與哪個表是多對多關系,column:外鍵,我引用別人的外鍵 --> <many-to-many class="Role" column="role_id"></many-to-many> </set> </class> </hibernate-mapping>
Role.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!-- 配置表與實體對象的關系 --> <!-- package屬性:填寫一個包名.在元素內部凡是需要書寫完整類名的屬性,可以直接寫簡答類名了. --> <hibernate-mapping package="cn.qlq.domain" > <!-- class元素: 配置實體與表的對應關系的 name: 完整類名 table:數據庫表名 --> <class name="Role" table="sys_role" > <!-- id元素:配置主鍵映射的屬性 name: 填寫主鍵對應屬性名 column(可選): 填寫表中的主鍵列名.默認值:列名會默認使用屬性名 type(可選):填寫列(屬性)的類型.hibernate會自動檢測實體的屬性類型. 每個類型有三種填法: java類型|hibernate類型|數據庫類型 not-null(可選):配置該屬性(列)是否不能為空. 默認值:false length(可選):配置數據庫中列的長度. 默認值:使用數據庫類型的最大長度 --> <id name="role_id" > <!-- generator:主鍵生成策略 --> <!--identity : 主鍵自增.由數據庫來維護主鍵值.錄入時不需要指定主鍵. --> <generator class="native"></generator> </id> <!-- property元素:除id之外的普通屬性映射 name: 填寫屬性名 column(可選): 填寫列名 type(可選):填寫列(屬性)的類型.hibernate會自動檢測實體的屬性類型. 每個類型有三種填法: java類型|hibernate類型|數據庫類型 not-null(可選):配置該屬性(列)是否不能為空. 默認值:false length(可選):配置數據庫中列的長度. 默認值:使用數據庫類型的最大長度 --> <property name="role_name" length="20"/> <property name="role_state"/> <!-- 集合,多對多關系,在配置文件中配置 --> <!-- name:集合屬性名字 table:中間表名 --> <set name="users" table="sys_user_role"> <!-- column:外鍵,別人引用我的外鍵列名 --> <key column="role_id" ></key> <!-- class:我與哪個表是多對多關系,column:外鍵,我引用別人的外鍵 --> <many-to-many class="User" column="user_id"></many-to-many> </set> </class> </hibernate-mapping>
4.測試建表結果:
隨便執行一個hibernate測試,會加載主配置文件並進行建表。
mysql> desc sys_user; +------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+----------------+ | user_id | bigint(20) | NO | PRI | NULL | auto_increment | | User_name | varchar(20) | YES | | NULL | | | user_state | char(1) | YES | | NULL | | +------------+-------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> desc sys_role; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | role_id | bigint(20) | NO | PRI | NULL | auto_increment | | role_name | varchar(20) | YES | | NULL | | | role_state | varchar(255) | YES | | NULL | | +------------+--------------+------+-----+---------+----------------+ 3 rows in set (0.00 sec) mysql> desc sys_user_role; +---------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+------------+------+-----+---------+-------+ | user_id | bigint(20) | NO | PRI | NULL | | | role_id | bigint(20) | NO | PRI | NULL | | +---------+------------+------+-----+---------+-------+ 2 rows in set (0.00 sec)
5.修改ORM配置中set元素配置對set元素的進一步解釋
User.hbm.xml

Role.hbm.xml

修改之后查看建表語句:
mysql> show create table sys_user_role\G *************************** 1. row *************************** Table: sys_user_role Create Table: CREATE TABLE `sys_user_role` ( `user_id1` bigint(20) NOT NULL, `role_id1` bigint(20) NOT NULL, PRIMARY KEY (`role_id1`,`user_id1`), KEY `FKgxeccay1ha1igqs2myct720lt` (`user_id1`), CONSTRAINT `FKgxeccay1ha1igqs2myct720lt` FOREIGN KEY (`user_id1`) REFERENCES `sys_user` (`user_id`) CONSTRAINT `FKtfvi95hnfedqqxi3rk1qmrwy7` FOREIGN KEY (`role_id1`) REFERENCES `sys_role` (`role_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec)
總結:
<set name="users" table="sys_user_role"> <!-- column:外鍵,別人引用我的外鍵列名 (可以簡單的理解為中間表的列名)--> <key column="role_id1" ></key> <!-- class:我與哪個表是多對多關系,column:外鍵,我引用別人的外鍵 --> <many-to-many class="User" column="user_id1"></many-to-many> </set>
個人認為set元素更像是配置我與中間表的關系,key元素可以理解為中間表指向我的外鍵的名字,
many-to-many中的class指的是與我是多對多的對象類名,column是在中間表中其對應的外鍵名字。
2.多對多操作
--------------------------第一次測試-----------------
1.測試保存:
/** *測試保存(多對多) */ @Test public void fun1() { //1.獲取session Session session = HibernateUtil.openSession(); //2.開啟事務 Transaction tx = session.beginTransaction(); //3.構造數據(張三-總監、經理,李四---總監) User u1 = new User(); u1.setUser_name("張三"); User u2 = new User(); u2.setUser_name("李四"); Role r1 = new Role(); r1.setRole_name("總監"); Role r2 = new Role(); r2.setRole_name("經理"); u1.getRoles().add(r1); u1.getRoles().add(r2); u2.getRoles().add(r1); r1.getUsers().add(u1); r1.getUsers().add(u2); r2.getUsers().add(u1); session.save(u1); session.save(u2); session.save(r1); session.save(r1); //4.提交數據 tx.commit(); //5.關閉session session.close(); }
執行會報錯,因為兩個表都維護關系,所以會像中間表插入兩次記錄,導致插入重復。如下錯誤:

解決辦法:
- 第一鍾:將一方維護關系的代碼注釋掉:(一般開發中多對多的關系中都有一方放棄維護關系)

- 第二種:配置文件中,設置一方放棄維護關系,例如:設置user放棄維護關系(一般開發中多對多的關系中都有一方放棄維護關系)

2.測試修改:
/** *新增一個角色,並給張三新增加一個角色 */ @Test public void fun2() { //1.獲取session Session session = HibernateUtil.openSession(); //2.開啟事務 Transaction tx = session.beginTransaction(); //3.構造數據(張三-總監、經理,李四---總監) User u1 = session.get(User.class, 1l); Role r3 = new Role(); r3.setRole_name("太監"); session.save(r3);//保存新角色 u1.getRoles().add(r3);//u1處於持久態,因此不用執行更新語句也可以更新 //4.提交數據 tx.commit(); //5.關閉session session.close(); }
3.測試給張三刪除一個角色
/** *為張三刪除一個太監角色 */ @Test public void fun3() { //1.獲取session Session session = HibernateUtil.openSession(); //2.開啟事務 Transaction tx = session.beginTransaction(); //3.構造數據(張三-總監、經理,李四---總監) User u1 = session.get(User.class, 1l); Role r1 = session.get(Role.class, 3l); u1.getRoles().remove(r1);//u1處於持久態,因此不用執行更新語句也可以更新 //4.提交數據 tx.commit(); //5.關閉session session.close(); }
查看發出的SQL:
Hibernate: select user0_.user_id as user_id1_3_0_, user0_.User_name as User_nam2_3_0_, user0_.user_state as user_sta3_3_0_ from sys_user user0_ where user0_.user_id=? Hibernate: select role0_.role_id as role_id1_2_0_, role0_.role_name as role_nam2_2_0_, role0_.role_state as role_sta3_2_0_ from sys_role role0_ where role0_.role_id=? Hibernate: select roles0_.user_id as user_id1_4_0_, roles0_.role_id as role_id2_4_0_, role1_.role_id as role_id1_2_1_, role1_.role_name as role_nam2_2_1_, role1_.role_state as role_sta3_2_1_ from sys_user_role roles0_ inner join sys_role role1_ on roles0_.role_id=role1_.role_id where roles0_.user_id=? Hibernate: delete from sys_user_role where user_id=? and role_id=?
---------------------------第二次測試------------------
1.添加一個張三用戶,並給其添加兩個角色:經理和總監
/** * 測試1:添加一個張三用戶 * 添加兩個角色:經理、總監 */ @Test public void test1(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); /******S 開始業務邏輯*************/ User u1 = new User(); u1.setUser_name("張三"); Role r1 = new Role(); Role r2 = new Role(); r1.setRole_name("總監"); r2.setRole_name("經理"); u1.getRoles().add(r1); u1.getRoles().add(r2); session.save(u1); session.save(r1); session.save(r2); /******E 開始業務邏輯*************/ tx.commit(); }
SQL:
Hibernate: insert into sys_user (user_name, user_state) values (?, ?) Hibernate: insert into sys_role (role_name, role_state) values (?, ?) Hibernate: insert into sys_role (role_name, role_state) values (?, ?) Hibernate: insert into sys_user_role (user_id, role_id) values (?, ?) Hibernate: insert into sys_user_role (user_id, role_id) values (?, ?)
結果:
mysql> select * from sys_user; +---------+-----------+------------+ | user_id | user_name | user_state | +---------+-----------+------------+ | 1 | 張三 | NULL | +---------+-----------+------------+ 1 row in set (0.03 sec) mysql> select * from sys_role; +---------+-----------+------------+ | role_id | role_name | role_state | +---------+-----------+------------+ | 1 | 總監 | NULL | | 2 | 經理 | NULL | +---------+-----------+------------+ 2 rows in set (0.00 sec) mysql> select * from sys_user_role; +---------+---------+ | user_id | role_id | +---------+---------+ | 1 | 1 | | 1 | 2 | +---------+---------+ 2 rows in set (0.00 sec)
2.給上面的張三解除與總監角色的關聯關系
/** * 測試2:給上面的張三解除與總監角色的關聯關系 */ @Test public void test2(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); /******S 開始業務邏輯*************/ //get方法獲取的對象都是持久態 User user = session.get(User.class,1l ); Role role = session.get(Role.class, 1l); user.getRoles().remove(role); /******E 開始業務邏輯*************/ tx.commit(); }
SQL:
Hibernate: select user0_.user_id as user_id1_3_0_, user0_.user_name as user_nam2_3_0_, user0_.user_state as user_sta3_3_0_ from sys_user user0_ where user0_.user_id=? Hibernate: select role0_.role_id as role_id1_2_0_, role0_.role_name as role_nam2_2_0_, role0_.role_state as role_sta3_2_0_ from sys_role role0_ where role0_.role_id=? Hibernate: select roles0_.user_id as user_id1_4_0_, roles0_.role_id as role_id2_4_0_, role1_.role_id as role_id1_2_1_, role1_.role_name as role_nam2_2_1_, role1_.role_state as role_sta3_2_1_ from sys_user_role roles0_ inner join sys_role role1_ on roles0_.role_id=role1_.role_id where roles0_.user_id=? Hibernate: delete from sys_user_role where user_id=? and role_id=?
結果:
mysql> select * from sys_user; +---------+-----------+------------+ | user_id | user_name | user_state | +---------+-----------+------------+ | 1 | 張三 | NULL | +---------+-----------+------------+ 1 row in set (0.00 sec) mysql> select * from sys_role; +---------+-----------+------------+ | role_id | role_name | role_state | +---------+-----------+------------+ | 1 | 總監 | NULL | | 2 | 經理 | NULL | +---------+-----------+------------+ 2 rows in set (0.00 sec) mysql> select * from sys_user_role; +---------+---------+ | user_id | role_id | +---------+---------+ | 1 | 2 | +---------+---------+ 1 row in set (0.00 sec)
3.刪除經理角色,同時刪除與張三的綁定關系
/** * 測試3:刪除經理角色,同時刪除與張三的綁定關系 */ @Test public void test3(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); /******S 開始業務邏輯*************/ //get方法獲取的對象都是持久態 User user = session.get(User.class,1l ); Role role = session.get(Role.class, 2l); session.delete(role); /******E 開始業務邏輯*************/ tx.commit(); }
SQL:
Hibernate: select user0_.user_id as user_id1_3_0_, user0_.user_name as user_nam2_3_0_, user0_.user_state as user_sta3_3_0_ from sys_user user0_ where user0_.user_id=? Hibernate: select role0_.role_id as role_id1_2_0_, role0_.role_name as role_nam2_2_0_, role0_.role_state as role_sta3_2_0_ from sys_role role0_ where role0_.role_id=? Hibernate: delete from sys_user_role where role_id=? Hibernate: delete from sys_role where role_id=?
結果:
mysql> select * from sys_role; +---------+-----------+------------+ | role_id | role_name | role_state | +---------+-----------+------------+ | 1 | 總監 | NULL | +---------+-----------+------------+ 1 row in set (0.00 sec) mysql> select * from sys_user_role; Empty set (0.00 sec)
4.新增一個秘書角色,並賦給張三該角色
/** * 測試4:新增一個秘書角色,並賦給張三該角色 */ @Test public void test4(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); /******S 開始業務邏輯*************/ //get方法獲取的對象都是持久態 Role r1 = new Role(); r1.setRole_name("秘書"); User user = session.get(User.class,1l); user.getRoles().add(r1); session.save(r1); session.update(user); /******E 開始業務邏輯*************/ tx.commit(); }
SQL:
Hibernate: select user0_.user_id as user_id1_3_0_, user0_.user_name as user_nam2_3_0_, user0_.user_state as user_sta3_3_0_ from sys_user user0_ where user0_.user_id=? Hibernate: select roles0_.user_id as user_id1_4_0_, roles0_.role_id as role_id2_4_0_, role1_.role_id as role_id1_2_1_, role1_.role_name as role_nam2_2_1_, role1_.role_state as role_sta3_2_1_ from sys_user_role roles0_ inner join sys_role role1_ on roles0_.role_id=role1_.role_id where roles0_.user_id=? Hibernate: insert into sys_role (role_name, role_state) values (?, ?) Hibernate: insert into sys_user_role (user_id, role_id) values (?, ?)
結果:
mysql> select * from sys_role; +---------+-----------+------------+ | role_id | role_name | role_state | +---------+-----------+------------+ | 1 | 總監 | NULL | | 3 | 秘書 | NULL | +---------+-----------+------------+ 2 rows in set (0.00 sec) mysql> select * from sys_user_role; +---------+---------+ | user_id | role_id | +---------+---------+ | 1 | 3 | +---------+---------+ 1 row in set (0.00 sec)
5.修改秘書角色為總監秘書(不影響與用戶的關聯)
/** * 測試5:修改秘書角色為總監秘書(不影響與用戶的關聯) */ @Test public void test5(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); /******S 開始業務邏輯*************/ //get方法獲取的對象都是持久態 Role role = session.get(Role.class,3l); role.setRole_name("總監秘書"); session.update(role); /******E 開始業務邏輯*************/ tx.commit(); }
SQL:
Hibernate: select role0_.role_id as role_id1_2_0_, role0_.role_name as role_nam2_2_0_, role0_.role_state as role_sta3_2_0_ from sys_role role0_ where role0_.role_id=? Hibernate: update sys_role set role_name=?, role_state=? where role_id=?
結果:
mysql> select * from sys_user_role; +---------+---------+ | user_id | role_id | +---------+---------+ | 1 | 3 | +---------+---------+ 1 row in set (0.00 sec) mysql> select * from sys_role; +---------+-----------+------------+ | role_id | role_name | role_state | +---------+-----------+------------+ | 1 | 總監 | NULL | | 3 | 總監秘書 | NULL | +---------+-----------+------------+ 2 rows in set (0.00 sec)
6.刪除一個用戶,會自動刪除中間表
mysql> select * from sys_user_role; +---------+---------+ | user_id | role_id | +---------+---------+ | 1 | 3 | +---------+---------+ 1 row in set (0.00 sec) mysql> select * from sys_role; +---------+-----------+------------+ | role_id | role_name | role_state | +---------+-----------+------------+ | 1 | 總監 | NULL | | 3 | 總監秘書 | NULL | +---------+-----------+------------+ 2 rows in set (0.00 sec)
SQL:
Hibernate: select user0_.user_id as user_id1_3_0_, user0_.user_name as user_nam2_3_0_, user0_.user_state as user_sta3_3_0_ from sys_user user0_ where user0_.user_id=? Hibernate: delete from sys_user_role where user_id=? Hibernate: delete from sys_user where user_id=?
結果:
mysql> select * from sys_user; Empty set (0.00 sec) mysql> select * from sys_role; +---------+-----------+------------+ | role_id | role_name | role_state | +---------+-----------+------------+ | 1 | 總監 | NULL | | 3 | 總監秘書 | NULL | +---------+-----------+------------+ 2 rows in set (0.00 sec) mysql> select * from sys_user_role; Empty set (0.00 sec)
3.進階操作
1.inverse屬性:
一般開發中遇到多對多的關系總有一方放棄維護關系,至於是哪一方要看具體的業務需求。可以在代碼中放棄維護,也可以在配置文件中放棄維護。例如錄入員工時需要為員工指定所屬角色,那么業務方向就是由員工維護角色,角色不需要維護與員工的關系。
- 代碼中放棄維護角色:
/** *測試保存(多對多) */ @Test public void fun1() { //1.獲取session Session session = HibernateUtil.openSession(); //2.開啟事務 Transaction tx = session.beginTransaction(); //3.構造數據(張三-總監、經理,李四---總監) User u1 = new User(); u1.setUser_name("張三"); User u2 = new User(); u2.setUser_name("李四"); Role r1 = new Role(); r1.setRole_name("總監"); Role r2 = new Role(); r2.setRole_name("經理"); u1.getRoles().add(r1); u1.getRoles().add(r2); u2.getRoles().add(r1); //角色放棄維護與員工的關系 // r1.getUsers().add(u1); // r1.getUsers().add(u2); // r2.getUsers().add(u1); session.save(r1); session.save(r2); session.save(u1); session.save(u2); //4.提交數據 tx.commit(); //5.關閉session session.close(); }
- Role.hbm.xml配置文件中放棄維護關系inverse屬性為true即是放棄維護關系

2.級聯操作 cascade屬性
save-update :級聯保存或更新
delete:級聯刪除
all:等於save-update+delete
1.級聯保存或者更新:
例如我們新增一個角色並且給張三賦予新角色的代碼如下:
@Test public void fun2() { //1.獲取session Session session = HibernateUtil.openSession(); //2.開啟事務 Transaction tx = session.beginTransaction(); //3.構造數據(張三-總監、經理,李四---總監) User u1 = session.get(User.class, 1l); Role r3 = new Role(); r3.setRole_name("太監222"); session.save(r3);//保存新角色 u1.getRoles().add(r3);//u1處於持久態,因此不用執行更新語句也可以更新 //4.提交數據 tx.commit(); //5.關閉session session.close(); }
我們希望在更新user的時候會級聯保存角色,也就是省區一行session.save(r3)對象。
(1)修改User.hbm.xml

(2)將代碼保存角色的那一行代碼注釋掉

(3)測試並查看SQL:
Hibernate: select user0_.user_id as user_id1_3_0_, user0_.User_name as User_nam2_3_0_, user0_.user_state as user_sta3_3_0_ from sys_user user0_ where user0_.user_id=? Hibernate: select roles0_.user_id as user_id1_4_0_, roles0_.role_id as role_id2_4_0_, role1_.role_id as role_id1_2_1_, role1_.role_name as role_nam2_2_1_, role1_.role_state as role_sta3_2_1_ from sys_user_role roles0_ inner join sys_role role1_ on roles0_.role_id=role1_.role_id where roles0_.user_id=? Hibernate: insert into sys_role (role_name, role_state) values (?, ?) Hibernate: insert into sys_user_role (user_id, role_id) values (?, ?)
2.級聯刪除:
修改User.hbm.xml,開啟級聯刪除:

測試代碼:(會級聯去刪除角色表,如果角色表對應記錄被其他用戶引用會報錯)
/** *刪除張三,查看級聯刪除角色 */ @Test public void fun4() { //1.獲取session Session session = HibernateUtil.openSession(); //2.開啟事務 Transaction tx = session.beginTransaction(); //3.構造數據(張三-總監、經理,李四---總監) User u1 = session.get(User.class, 5l); session.delete(u1); //4.提交數據 tx.commit(); //5.關閉session session.close(); }
查看發出的SQL:
Hibernate: select user0_.user_id as user_id1_3_0_, user0_.User_name as User_nam2_3_0_, user0_.user_state as user_sta3_3_0_ from sys_user user0_ where user0_.user_id=? Hibernate: select roles0_.user_id as user_id1_4_0_, roles0_.role_id as role_id2_4_0_, role1_.role_id as role_id1_2_1_, role1_.role_name as role_nam2_2_1_, role1_.role_state as role_sta3_2_1_ from sys_user_role roles0_ inner join sys_role role1_ on roles0_.role_id=role1_.role_id where roles0_.user_id=? Hibernate: delete from sys_user_role where user_id=? Hibernate: delete from sys_role where role_id=? Hibernate: delete from sys_role where role_id=? Hibernate: delete from sys_user where user_id=?
總結:
O 對象 兩方都使用集合. R 關系型數據庫 使用中間表.至少兩列.作為外鍵引用兩張表的主鍵. M 映射文件 多: <set name="" table="中間表名" > <key column="別人引用我" /> <man-to-many class="" column="我引用別人的" /> </set> 操作:操作管理級別屬性. cascade: 級聯操作 減少我們書寫的操作代碼. none(默認值) 不級聯 save-update: 級聯保存 delete: 級聯刪除 all: 級聯保存+級聯刪除 結論: 可以使用save-update.不推薦使用delete. 也可以不用cascade. inverse: 反轉關系維護 屬於性能優化.必須選擇一方放棄維護主鍵關系.哪方放棄要看業務方向.
補充:多對多的時候經常用到查詢,比如上面查詢用戶ID為1的用戶具有的角色
用HQL判斷兩個實體間是否存在一對多關系,用的 in elements, 注意in elements 只能用於where 從句中
語法如下:
@Test public void fun5() { // 1.獲取session Session session = HibernateUtil.openSession(); String hql = "from Role r where ? in elements(r.users)"; Query query = session.createQuery(hql); User user = new User(); user.setUser_id(1L); query.setParameter(0, user); List<Role> roles = query.list(); System.out.println(roles); }
查看SQL語句如下:
Hibernate:
select
role0_.role_id as role_id1_0_,
role0_.role_name as role_nam2_0_,
role0_.role_state as role_sta3_0_
from
sys_role role0_
where
? in (
select
users1_.user_id
from
sys_user_role users1_
where
role0_.role_id=users1_.role_id
)
Hibernate:
select
users0_.role_id as role_id2_2_0_,
users0_.user_id as user_id1_2_0_,
user1_.user_id as user_id1_1_1_,
user1_.User_name as User_nam2_1_1_,
user1_.user_state as user_sta3_1_1_
from
sys_user_role users0_
inner join
sys_user user1_
on users0_.user_id=user1_.user_id
where
users0_.role_id=?
Hibernate:
select
users0_.role_id as role_id2_2_0_,
users0_.user_id as user_id1_2_0_,
user1_.user_id as user_id1_1_1_,
user1_.User_name as User_nam2_1_1_,
user1_.user_state as user_sta3_1_1_
from
sys_user_role users0_
inner join
sys_user user1_
on users0_.user_id=user1_.user_id
where
users0_.role_id=?
