hibernate 一對多、多對多操作

表之間的關(guān)系

  1. 一對多

    一個部門有多個員工,一個員工只能屬于某一個部門
    一個班級有多個學(xué)生,一個學(xué)生只能屬于一個班級

  2. 多對多

    一個老師教多個學(xué)生,一個學(xué)生可以被多個老師教
    一個學(xué)生可以先擇多門課程,一門課程可以被多個學(xué)生選擇
    一個用戶可以選擇多個角色,一個角色也可以被多個用戶選擇

  3. 一對一

    一個公司只能對應(yīng)一個注冊地址

表之間關(guān)系建表原則

  1. 一對多

    在多的一方創(chuàng)建一個外鍵,指向一的一方的主鍵

  2. 多對多

    創(chuàng)建一個中間表,中間表至少有兩個字段,分別作為外鍵指向多對多雙方的主鍵

  3. 一對一

    唯一外鍵對應(yīng)或主鍵對應(yīng)

多表操作

一對多
  1. 建立表

    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;
    
  2. 創(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;
    }
    
  3. 創(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>
    
  4. 創(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>
    
  5. 引入工具類

    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();
        }
    
    }
    
  6. 編寫測試類

    級聯(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();
          }
     }
    
多對多
  1. 建立表

       # 用戶表
           #一個用戶可以有多個角色
            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
  2. 創(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<>();
       }
    
  3. 添加配置文件

    <?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>
    
  4. 在核心配置文件當(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>
    
    
  5. 編寫測試類

    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();
        }
    }
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文包括:1、一對多結(jié)構(gòu)的準(zhǔn)備2、雙向關(guān)聯(lián)與單向關(guān)聯(lián)3、級聯(lián)保存4、級聯(lián)刪除5、cascade 屬性——級聯(lián)6、i...
    廖少少閱讀 1,291評論 1 6
  • 本文包括:1、Hibernate 的查詢方式2、HQL (Hibernate Query Language) 查詢...
    廖少少閱讀 2,725評論 0 15
  • layout: posttitle: hibernatesubtitle: 用法date: ...
    蟲兒飛ZLEI閱讀 380評論 0 1
  • 本文包括: 1、CRM 項目的整體介紹 2、Hibernate 框架概述 3、Hibernate 快速入門 4、H...
    廖少少閱讀 3,532評論 9 66
  • 本文包括:1、Hibernate的持久化類2、Hibernate 持久化對象的三個狀態(tài)(難點)3、Hibernat...
    廖少少閱讀 1,594評論 0 13

友情鏈接更多精彩內(nèi)容