表之間的關(guān)系
- 一對多
一個部門有多個員工,一個員工只能屬于某一個部門
一個班級有多個學(xué)生,一個學(xué)生只能屬于一個班級 - 多對多
一個老師教多個學(xué)生,一個學(xué)生可以被多個老師教
一個學(xué)生可以先擇多門課程,一門課程可以被多個學(xué)生選擇
一個用戶可以選擇多個角色,一個角色也可以被多個用戶選擇 - 一對一
一個公司只能對應(yīng)一個注冊地址
表之間關(guān)系建表原則
- 一對多
在多的一方創(chuàng)建一個外鍵,指向一的一方的主鍵
- 多對多
創(chuàng)建一個中間表,中間表至少有兩個字段,分別作為外鍵指向多對多雙方的主鍵
- 一對一
唯一外鍵對應(yīng)或主鍵對應(yīng)
多表操作
一對多
-
建立表
CREATE TABLE `linkman` ( `link_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '聯(lián)系人編號(主鍵)', `link_name` varchar(16) DEFAULT NULL COMMENT '聯(lián)系人姓名', `link_cust_id` bigint(32) NOT NULL COMMENT '客戶id', `link_gender` char(1) DEFAULT NULL COMMENT '聯(lián)系人性別', `link_phone` varchar(16) DEFAULT NULL COMMENT '聯(lián)系人辦公電話', `link_mobile` varchar(16) DEFAULT NULL COMMENT '聯(lián)系人手機(jī)', `link_email` varchar(64) DEFAULT NULL COMMENT '聯(lián)系人郵箱', `link_qq` varchar(16) DEFAULT NULL COMMENT '聯(lián)系人qq', `link_position` varchar(16) DEFAULT NULL COMMENT '聯(lián)系人職位', `link_memo` varchar(512) DEFAULT NULL COMMENT '聯(lián)系人備注', PRIMARY KEY (`link_id`) ) comment '聯(lián)系人表' ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; CREATE TABLE `customer` ( `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客戶編號(主鍵)', `cust_name` varchar(32) NOT NULL COMMENT '客戶名稱(公司名稱)', `cust_source` varchar(32) DEFAULT NULL COMMENT '客戶信息來源', `cust_industry` varchar(32) DEFAULT NULL COMMENT '客戶所屬行業(yè)', `cust_level` varchar(32) DEFAULT NULL COMMENT '客戶級別', `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定電話', `cust_mobile` varchar(16) DEFAULT NULL COMMENT '移動電話', PRIMARY KEY (`cust_id`) ) comment '客戶表' ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; -
創(chuàng)建實體類并設(shè)置表之間的關(guān)系
/** * 客戶實體類 * @author zhou * @create 2019/11/19/21:33 * @class com.zhou.domian.Linkman */ @Getter @Setter public class Customer { private long cust_id; private String cust_name; private String cust_source; private String cust_industry; private String cust_level; private String cust_phone; private String cust_mobile; // 一個客戶有多個聯(lián)系人 private Set<Linkman> linkmens = new HashSet<>(); }/** * 聯(lián)系人實體類 * @author zhou * @create 2019/11/19/21:11 * @class com.zhou.domian.Linkman */ @Getter @Setter public class Linkman { private Long link_id; private String link_name; private String link_gender; private String link_phone; private String link_mobile; private String link_email; private String link_qq; private String link_position; private String link_memo; // 聯(lián)系人表關(guān)聯(lián)一個客戶 private Customer customer; } -
創(chuàng)建映射文件
<?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"> <hibernate-mapping> <class name="com.zhou.domian.Customer" table="customer" schema="hibernate"> <!-- 建立那個字段是主鍵 --> <id name="cust_id" column="cust_id" > <!-- 主鍵的生成策略 --> <generator class="native"/> </id> <!-- 建立POJO類字段和數(shù)據(jù)庫字段關(guān)聯(lián) --> <property name="cust_name" column="cust_name"/> <property name="cust_source" column="cust_source"/> <property name="cust_industry" column="cust_industry"/> <property name="cust_level" column="cust_level"/> <property name="cust_phone" column="cust_phone"/> <property name="cust_mobile" column="cust_mobile"/> <!-- set標(biāo)簽的name屬性: 多的一方的集合的屬性名稱 --> <set name="linkmens"> <!-- key的 column表示多的一方外鍵名 --> <key column="link_cust_id"></key> <!-- one-to-many的class屬性表示多的一方類的全限定名 --> <one-to-many class="com.zhou.domian.Linkman"></one-to-many> </set> </class> </hibernate-mapping><?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"> <hibernate-mapping> <class name="com.zhou.domian.Linkman" table="linkman" schema="hibernate"> <id name="link_id" column="link_id"> <generator class="native"></generator> </id> <property name="link_name" column="link_name"/> <property name="link_gender" column="link_gender"/> <property name="link_phone" column="link_phone"/> <property name="link_mobile" column="link_mobile"/> <property name="link_email" column="link_email"/> <property name="link_qq" column="link_qq"/> <property name="link_position" column="link_position"/> <property name="link_memo" column="link_memo"/> <!--多對一 name: 一的一方對象的名字 class: 一的一方類的全限定名 column: 多的一方外鍵ID的名稱 --> <many-to-one name="customer" column="link_cust_id" class="com.zhou.domian.Customer" /> </class> </hibernate-mapping> -
創(chuàng)建核心配置文件
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 設(shè)置連接數(shù)據(jù)庫的url和用戶名和密碼和數(shù)據(jù)庫驅(qū)動--> <property name="url">jdbc:mysql:///hibernate</property> <property name="username">root</property> <property name="password">123456</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <!-- 打印SQL語句 --> <property name="hibernate.show_sql">true</property> <!-- 格式化SQL --> <property name="hibernate.format_sql">true</property> <!-- 設(shè)置hibernate的方言 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- 設(shè)置自動創(chuàng)建表 --> <property name="hibernate.hbm2ddl.auto">create</property> <!--阿里巴巴 Druid 連接池 注意:如果使用Druid連接池的話需要把數(shù)據(jù)基本連接屬性改為Druid的屬性--> <property name="hibernate.connection.provider_class"> com.alibaba.druid.support.hibernate.DruidConnectionProvider </property> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize">1</property> <property name="minIdle">5</property> <property name="maxActive">20</property> <!-- 配置獲取連接等待超時的時間 --> <property name="maxWait">60000</property> <!-- 配置間隔多久才進(jìn)行一次檢測,檢測需要關(guān)閉的空閑連接,單位是毫秒 --> <property name="timeBetweenEvictionRunsMillis">60000</property> <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 --> <property name="minEvictableIdleTimeMillis">300000</property> <!-- 設(shè)置事務(wù)隔離級別 --> <property name="hibernate.connection.isolation">3</property> <!-- 創(chuàng)建一個session綁定到當(dāng)前線程 --> <property name="current_session_context_class">thread</property> <!-- 加載映射(mapper)文件 --> <mapping resource="mapper/customer.hbm.xml"></mapping> <mapping resource="mapper/linkman.hbm.xml"/> </session-factory> </hibernate-configuration> -
引入工具類
package com.zhou.utils; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /** * @author zhou * @create 2019/11/12/21:21 * @class com.zhou.utils.HibernateUtils */ public class HibernateUtils { public static final SessionFactory sessionFactory; static { // 讀取配置,并創(chuàng)建工廠類SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); } /** * 獲取Session對象 * @return Session */ public static Session getSession () { return sessionFactory.openSession(); } /** * 使用時必須要在hibernate核心配置文件中配置 * <property name="current_session_context_class">thread</property> * 獲取Session對象,不過是從內(nèi)部已經(jīng)綁定好了ThreadLocal,獲取的Session對象 * @return Session */ public static Session getCurrentSession(){ return sessionFactory.getCurrentSession(); } } -
編寫測試類
級聯(lián)操作與懶加載
注意: 誰需要級聯(lián)操作,就在mapper(映射文件)中加cascade屬性
級聯(lián)的配置屬性6.1 級聯(lián)查詢與懶加載
<many-to-one name="customer" column="link_cust_id" class="com.zhou.domian.Customer" lazy="proxy" />/** * @author zhou * @create 2019/11/19/23:15 * @class com.zhou.test.HibernateORMTest */ public class HibernateORMTest { /** * 級聯(lián)查詢與懶加載 */ @Test public void get(){ Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); Linkman linkman = session.get(Linkman.class, 1L); transaction.commit(); System.out.println(linkman.getLink_name()); /** * org.hibernate.LazyInitializationException: could not initialize proxy [com.zhou.domian.Customer#1] - no Session * 報這個錯誤是因為使用hibernate默認(rèn)使用了懶加載的方式,要使用到另外一個對象時才會發(fā)送SQL去查詢, * 而getCurrentSession()方法取出來的Session在commit后,會自動把session.close()掉,所以報no session的錯誤 * 如果不想要對象懶加載可以在mapper配置文件中配置,lazy: 設(shè)置是否懶加載,默認(rèn)為proxy(懶加載),false為不啟用懶加載 * <many-to-one name="customer" column="link_cust_id" class="com.zhou.domian.Customer" lazy="proxy" /> */ System.out.println(linkman.getCustomer().getCust_name()); } }6.2. 級聯(lián)保存
<set name="linkmens" cascade="save-update" lazy="false"> <!-- key的 column表示多的一方外鍵名 --> <key column="link_cust_id"></key> <!-- one-to-many的class屬性表示多的一方類的全限定名 --> <one-to-many class="com.zhou.domian.Linkman"></one-to-many> </set>/** * @author zhou * @create 2019/11/19/23:15 * @class com.zhou.test.HibernateORMTest */ public class HibernateORMTest { /** * 一對多的級聯(lián)保存save, 雙向綁定,不需要設(shè)置cascade屬性 */ @Test public void save () { // 獲取Session對象并開啟事務(wù) Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 創(chuàng)建實體類并設(shè)置關(guān)系 Customer customer1 = new Customer(); Customer customer2 = new Customer(); Customer customer3 = new Customer(); customer1.setCust_name("customer1"); customer2.setCust_name("customer2"); customer3.setCust_name("customer3"); Linkman linkman1 = new Linkman(); Linkman linkman2 = new Linkman(); Linkman linkman3 = new Linkman(); linkman1.setLink_name("linkman1"); linkman2.setLink_name("linkman2"); linkman3.setLink_name("linkman3"); linkman1.setCustomer(customer1); linkman2.setCustomer(customer1); linkman3.setCustomer(customer3); customer1.getLinkmens().add(linkman1); customer1.getLinkmens().add(linkman2); customer2.getLinkmens().add(linkman3); // 保存數(shù)據(jù) session.save(customer1); session.save(customer2); session.save(customer3); session.save(linkman1); session.save(linkman2); session.save(linkman3); // 提交事務(wù) transaction.commit(); } /** * 一對多的級聯(lián)保存save, 單項綁定 */ @Test public void saveOne () { // 獲取Session對象并開啟事務(wù) Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 創(chuàng)建實體類并設(shè)置關(guān)系,單項綁定 Customer customer1 = new Customer(); Customer customer2 = new Customer(); Customer customer3 = new Customer(); customer1.setCust_name("customer1"); customer2.setCust_name("customer2"); customer3.setCust_name("customer3"); Linkman linkman1 = new Linkman(); Linkman linkman2 = new Linkman(); Linkman linkman3 = new Linkman(); linkman1.setLink_name("linkman1"); linkman2.setLink_name("linkman2"); linkman3.setLink_name("linkman3"); /** * java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - * save the transient instance before flushing: com.zhou.domian.Linkman * 持久態(tài)對象關(guān)聯(lián)了一個瞬時態(tài)對象,就會報瞬時對象異常 * 如果想要支持單項綁定,在mapper配置文件中添加cascade="save-update" * set標(biāo)簽的name屬性: 多的一方的集合的屬性名稱 * <set name="linkmens" cascade="save-update"> * key的 column表示多的一方外鍵名 * <key column="link_cust_id"></key> * one-to-many的class屬性表示多的一方類的全限定名 * <one-to-many class="com.zhou.domian.Linkman"></one-to-many> * </set> * */ customer1.getLinkmens().add(linkman1); customer1.getLinkmens().add(linkman2); customer2.getLinkmens().add(linkman3); // 保存數(shù)據(jù) session.save(customer1); session.save(customer2); session.save(customer3); // 提交事務(wù) transaction.commit(); } }6.3. 級聯(lián)刪除
<set name="linkmens" cascade="delete" lazy="false"> <!-- key的 column表示多的一方外鍵名 --> <key column="link_cust_id"></key> <!-- one-to-many的class屬性表示多的一方類的全限定名 --> <one-to-many class="com.zhou.domian.Linkman"></one-to-many> </set>public class HibernateORMTest { /** * 級聯(lián)刪除 */ @Test public void delete() { // 獲取Session對象并開啟事務(wù) Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 進(jìn)行查詢并刪除,如果沒有設(shè)置級聯(lián)屬性則不會級聯(lián)刪除,只會把附屬表的屬性先更新為null,在刪除主表中的數(shù)據(jù) Customer customer = session.get(Customer.class, 1L); session.delete(customer); // 提交事務(wù) transaction.commit(); } }6.4. 外鍵維護(hù)權(quán)inverse
<!-- inverse="true" 使對象放棄外鍵維護(hù)--> <!-- set標(biāo)簽的name屬性: 多的一方的集合的屬性名稱 --> <set name="linkmens" cascade="save-update, delete" inverse="true" lazy="false"> <!-- key的 column表示多的一方外鍵名 --> <key column="link_cust_id"></key> <!-- one-to-many的class屬性表示多的一方類的全限定名 --> <one-to-many class="com.zhou.domian.Linkman"></one-to-many> </set>public class HibernateORMTest{ /** * 級聯(lián)更新外鍵 * inverse外加維護(hù)權(quán),雙向綁定使用 */ @Test public void updateInverse() { // 獲取Session對象并開啟事務(wù) Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); Customer customer2 = session.get(Customer.class, 2L); Linkman linkman2 = session.get(Linkman.class, 2L); // 雙向綁定,如果雙向綁定,hibernate會發(fā)送兩個sql來更改同一個數(shù)據(jù),這就造成數(shù)據(jù)庫的壓力,需要進(jìn)行優(yōu)化 // 如果想要優(yōu)化,那就讓一方放棄外鍵維護(hù),需要設(shè)置inverse屬性讓一方放棄,默認(rèn)是false,false是不放棄, true是放棄 customer2.getLinkmens().add(linkman2); linkman2.setCustomer(customer2); // 提交事務(wù) transaction.commit(); } /** * 級聯(lián)更新外鍵 * 單項綁定 */ @Test public void update() { // 獲取Session對象并開啟事務(wù) Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); Customer customer2 = session.get(Customer.class, 2L); Linkman linkman2 = session.get(Linkman.class, 2L); // 單項綁定, 只需要一個對象進(jìn)行綁定. customer2.getLinkmens().add(linkman2); // linkman2.setCustomer(customer2); // 提交事務(wù) transaction.commit(); } }
多對多
-
建立表
# 用戶表 #一個用戶可以有多個角色 CREATE TABLE `user` ( `user_id` bigint(20) NOT NULL AUTO_INCREMENT, `user_code` varchar(255) DEFAULT NULL, `user_name` varchar(255) DEFAULT NULL, `user_password` varchar(255) DEFAULT NULL, `user_state` varchar(255) DEFAULT NULL, PRIMARY KEY (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4; #角色表 #一個角色可以被多個用戶選擇 CREATE TABLE `role` ( `role_id` bigint(20) NOT NULL AUTO_INCREMENT, `role_name` varchar(255) DEFAULT NULL, `role_memo` varchar(255) DEFAULT NULL, PRIMARY KEY (`role_id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4; # 中間表 CREATE TABLE `user_role` ( `role_id` bigint(20) NOT NULL, `user_id` bigint(20) NOT NULL, PRIMARY KEY (`user_id`,`role_id`), CONSTRAINT `user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`), CONSTRAINT `role_id_fk` FOREIGN KEY (`role_id`) REFERENCES `role` (`role_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;關(guān)系圖
關(guān)系圖.png -
創(chuàng)建實體類并建立關(guān)系
/** * @author zhou * @create 2019/11/24/19:33 * @class com.zhou.domian.User */ @Getter @Setter public class User { private long user_id; private String user_code; private String user_name; private String user_password; private String user_state; /** * 建立用戶對應(yīng)多個角色的映射 */ Set<Role> roles = new HashSet<>(); }/** * @author zhou * @create 2019/11/24/19:33 * @class com.zhou.domian.Role */ @Getter @Setter public class Role { private long role_id; private String role_name; private String role_memo; /** * 建立多角色對應(yīng)多用戶 */ private Set<User> users = new HashSet<>(); } -
添加配置文件
<?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"> <hibernate-mapping> <class name="com.zhou.domian.User" table="user" schema="hibernate"> <id name="user_id" column="user_id"> <generator class="native"></generator> </id> <property name="user_code" column="user_code"/> <property name="user_name" column="user_name"/> <property name="user_password" column="user_password"/> <property name="user_state" column="user_state"/> <!-- name: 是當(dāng)前集合屬性名稱 table: 是多對多中間表 <key column="role_id"></key> 當(dāng)前表的外鍵 <many-to-many column="role_id" class="com.zhou.domian.Role"/> column: 集合中對象的外鍵 class: 集合中對象的全路徑 --> <set name="roles" table="user_role" cascade ="save-update"> <key column="user_id"></key> <many-to-many class="com.zhou.domian.Role" column="role_id"/> </set> </class> </hibernate-mapping><?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"> <hibernate-mapping> <class name="com.zhou.domian.Role" table="role" schema="hibernate"> <!-- 建立那個字段是主鍵 --> <id name="role_id" column="role_id"> <!-- 主鍵的生成策略 --> <generator class="native"/> </id> <!-- 建立POJO類字段和數(shù)據(jù)庫字段關(guān)聯(lián) --> <property name="role_name" column="role_name"/> <property name="role_memo" column="role_memo"/> <!-- name: 是當(dāng)前集合屬性名稱 table: 是多對多中間表 <key column=""></key> 當(dāng)前表的外鍵 <many-to-many column="" class=""/> column: 集合中對象的外鍵 class: 集合中對象的全路徑 --> <set name="users" table="user_role" inverse="false"> <key column="role_id"></key> <many-to-many column="user_id" class="com.zhou.domian.User"/> </set> </class> </hibernate-mapping> -
在核心配置文件當(dāng)中添加兩個新配置
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- 設(shè)置連接數(shù)據(jù)庫的url和用戶名和密碼和數(shù)據(jù)庫驅(qū)動--> <property name="url">jdbc:mysql:///hibernate</property> <property name="username">root</property> <property name="password">123456</property> <property name="driverClass">com.mysql.jdbc.Driver</property> <!-- 打印SQL語句 --> <property name="hibernate.show_sql">true</property> <!-- 格式化SQL --> <property name="hibernate.format_sql">true</property> <!-- 設(shè)置hibernate的方言 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</property> <!-- 設(shè)置自動創(chuàng)建表 --> <property name="hibernate.hbm2ddl.auto">update</property> <!--阿里巴巴 Druid 連接池 注意:如果使用Druid連接池的話需要把數(shù)據(jù)基本連接屬性改為Druid的屬性--> <property name="hibernate.connection.provider_class"> com.alibaba.druid.support.hibernate.DruidConnectionProvider </property> <!-- 配置初始化大小、最小、最大 --> <property name="initialSize">1</property> <property name="minIdle">5</property> <property name="maxActive">20</property> <!-- 配置獲取連接等待超時的時間 --> <property name="maxWait">60000</property> <!-- 配置間隔多久才進(jìn)行一次檢測,檢測需要關(guān)閉的空閑連接,單位是毫秒 --> <property name="timeBetweenEvictionRunsMillis">60000</property> <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 --> <property name="minEvictableIdleTimeMillis">300000</property> <!-- 設(shè)置事務(wù)隔離級別 --> <property name="hibernate.connection.isolation">3</property> <!-- 創(chuàng)建一個session綁定到當(dāng)前線程 --> <property name="current_session_context_class">thread</property> <!-- 加載映射(mapper)文件 --> <!--一對多的映射文件--> <mapping resource="mapper/customer.hbm.xml"/> <mapping resource="mapper/linkman.hbm.xml"/> <!--添加多對多的映射文件--> <mapping resource="mapper/role.hbm.xml"/> <mapping resource="mapper/user.hbm.xml"/> </session-factory> </hibernate-configuration> -
編寫測試類
public class HibernateManyAndMany { /** * 雙向維護(hù) * 級聯(lián)保存,雙向維護(hù),從表開啟放棄外鍵維護(hù), 如在mapper映射文件中的多對多屬性中加上inverse="false",放棄外鍵維 * 雙向維護(hù)時,必須要有一方放棄外鍵維護(hù) * 如果兩邊都有維護(hù)的話, 就會有重復(fù)的的記錄,由于關(guān)系表是兩個字段作為共同主鍵,不能有相同的記錄 * 解決辦法 * 通常都是讓被動方放棄,用戶選角色,角色為被動方 */ @Test public void save() { // 獲取Session對象并開啟事務(wù) Session currentSession = HibernateUtils.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); User user1 = new User(); user1.setUser_name("user1"); User user2 = new User(); user2.setUser_name("user2"); User user3 = new User(); user3.setUser_name("user3"); Role role1 = new Role(); role1.setRole_name("施工員"); Role role2 = new Role(); role2.setRole_name("資料員"); Role role3 = new Role(); role3.setRole_name("項目經(jīng)理"); user1.getRoles().add(role1); user1.getRoles().add(role3); user2.getRoles().add(role1); user3.getRoles().add(role2); currentSession.save(user1); currentSession.save(user2); currentSession.save(user3); // 放棄外鍵維護(hù) currentSession.save(role1); currentSession.save(role2); currentSession.save(role3); // 提交事務(wù) transaction.commit(); } }/** * @author zhou * @create 2019/11/24/20:01 * @class com.zhou.test.HibarnateManyAndMany */ public class HibernateManyAndMany { /** * 級聯(lián)保存,單項綁定, 單項綁定需要配置cascade="save-update" */ @Test public void saveOne() { // 獲取Session對象并開啟事務(wù) Session currentSession = HibernateUtils.getCurrentSession(); Transaction transaction = currentSession.beginTransaction(); User user1 = new User(); user1.setUser_name("user1"); User user2 = new User(); user2.setUser_name("user2"); User user3 = new User(); user3.setUser_name("user3"); Role role1 = new Role(); role1.setRole_name("施工員"); Role role2 = new Role(); role2.setRole_name("資料員"); Role role3 = new Role(); role3.setRole_name("項目經(jīng)理"); user1.getRoles().add(role1); user1.getRoles().add(role3); user2.getRoles().add(role1); user3.getRoles().add(role2); currentSession.save(user1); currentSession.save(user2); currentSession.save(user3); // 提交事務(wù) transaction.commit(); } }多對多的級聯(lián)操作和一對多的級聯(lián)操作是一樣的
/** * @author zhou * @create 2019/11/24/20:01 * @class com.zhou.test.HibarnateManyAndMany */ public class HibernateManyAndMany { /** * 添加角色,雙向綁定,讓一方放棄外鍵維護(hù),需要設(shè)置inverse屬性讓一方放棄,默認(rèn)是false,false是不放棄, true是放棄 * 如果不讓一方放棄外鍵維護(hù)的話,會報錯 */ @Test public void addRole() { // 獲取Session并開啟事務(wù) Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 用戶3添加角色1 User user3 = session.get(User.class, 3L); Role role1 = session.get(Role.class, 1L); user3.getRoles().add(role1); role1.getUsers().add(user3); // 提交事務(wù) transaction.commit(); } /** * 單項維護(hù),添加角色 */ @Test public void addRoleOne() { // 獲取Session并開啟事務(wù) Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 用戶3添加角色1 User user3 = session.get(User.class, 3L); Role role1 = session.get(Role.class, 1L); user3.getRoles().add(role1); // 提交事務(wù) transaction.commit(); } /** * 關(guān)系操作,就是操作內(nèi)部的集合 * 把用戶1的角色3修改為角色2 */ @Test public void UpdateUserAndRole() { // 獲取Session并開啟事務(wù) Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 把用戶1的角色3修改為角色2 User user1 = session.get(User.class, 1L); Role role2 = session.get(Role.class, 2L); Role role3 = session.get(Role.class, 3L); // 刪除角色2 user1.getRoles().remove(role3); // 添加角色3 user1.getRoles().add(role2); // 提交事務(wù) transaction.commit(); } }

