Hibernate關係關聯中inverse(反轉)和cascade(級聯)操作

http://c.biancheng.net/view/4207.html(源網址)

在 Hibernate 的關聯關係中,可以使用單向關聯關係,也可以使用雙向關聯關係,在雙向關聯關係中,Hibernate 會同時控制雙方的關係,這樣在程序操作時,很容易出現重複操作的問題。

爲了解決這一問題,Hibernate 提供了反轉操作,同時,爲了在操作多表時,主表(主控方)操作後的數據能與關聯表的數據保持一致,Hibernate 還提供了級聯操作。接下來將對這兩種操作進行詳細講解。

反轉操作

在映射文件的 <set> 標籤中,有一個 inverse(反轉)屬性,它的作用是控制關聯的雙方由哪一方管理關聯關係。

inverse 屬性值是 boolean 類型的:
  • 當取值爲 false(默認值)時,表示由當前這一方管理雙方的關聯關係,如果雙方 inverse 屬性都爲 false 時,雙方將同時管理關聯關係。
  • 取值爲 true 時,表示當前一方放棄控制權,由對方管理雙方的關聯關係。


通常情況下,在一對多關聯關係中,會將“一”的一方的 inverse 屬性取值爲 true,即由“多”的一方維護關聯關係,否則會產生多餘的 SQL 語句;而在多對多的關聯關係中,任意設置一方的 inverse 屬性爲 true 即可。

通常情況下,這種問題有兩種解決方案:第一種是進行單向關聯,第二種是在一方的映射文件中,將 <set> 標籤的 inverse 屬性設置爲 true。 

  /*
    * 設置雙向的關聯,產生了多餘的SQL語句
    * 原來2號聯繫人屬於一號客戶。現在改爲屬於2號
    * */
    @Test
    public void demo6(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Customer customer = session.get(Customer.class, 2l);
        LinkMan linkMan = session.get(LinkMan.class, 1l);

        /*設置雙向關聯,產生了兩次更新外鍵的語句,
        * 結局方案:
        * 1、在一的一方設置外鍵維護權,放棄外鍵維護權    set配置inverse=“true”
        * 2、設置單向關聯
        * */
        customer.getLinkMans().add(linkMan);
        linkMan.setCustomer(customer);

        tx.commit();
    }

 

級聯操作

級聯操作是指當主控方執行任意操作時,其關聯對象也執行相同的操作,保持同步。在映射文件的 <set> 標籤中有個 cascade 屬性,該屬性用於設置是否對關聯對象採用級聯操作,其常用屬性如表 1 所示。
 
表 1 cascade屬性的屬性值
屬性值 描   述
save-update 在執行 save、update 或 saveOrUpdate 吋進行關聯操作
delete 在執行 delete 時進行關聯操作
delete-orphan 刪除所有和當前解除關聯關係的對象
all 所有情況下均進行關聯操作,但不包含 delete-orphan 的操作
all-delete-orphan 所有情況下均進行關聯操作
none 所有情況下均不進行關聯操作,這是默認值
瞭解了 cascade 的相關屬性後,下面通過案例講解 cascade 屬性在實際應用中的級聯操作。                                                   

1.如果沒有設置級聯操作,我們就要建立雙向的關聯。對於一對多的關係,我們應該在一的一方,通過集合將多的一方添加至其中,對於多的一方,通過一的一方的對象來設置。如demo實例。                                                                                 

2.設置級聯操作後,我們只需通過保存一方的數據即可。如demo2實例。                                                                           

3.級聯保存或更新demo3。                                                                                                                                                     

4.級聯刪除demo5。

   //保存兩個客戶、三個聯繫人  並建立關係
    public void demo(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        //創建兩客戶
        Customer customer1 = new Customer();
        customer1.setCust_name("小明");
        Customer customer2 = new Customer();
        customer2.setCust_name("小華");

        //創建三個聯繫人
        LinkMan linkMan1 = new LinkMan();
        linkMan1.setLkm_name("abc");
        LinkMan linkMan2 = new LinkMan();
        linkMan2.setLkm_name("bcd");
        LinkMan linkMan3 = new LinkMan();
        linkMan3.setLkm_name("cde");

        //設置關係
        linkMan1.setCustomer(customer1);
        linkMan2.setCustomer(customer1);
        linkMan3.setCustomer(customer2);
        customer1.getLinkMans().add(linkMan1);
        customer1.getLinkMans().add(linkMan2);
        customer2.getLinkMans().add(linkMan3);

        //保存數據
        session.save(linkMan1);
        session.save(linkMan2);
        session.save(linkMan3);
        session.save(customer1);
        session.save(customer2);
        tx.commit();
    }
    /*一對多隻保存一邊的數據不可以*/
    @Test
    public void demo1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Customer customer1 = new Customer();
        customer1.setCust_name("小明");
        LinkMan linkMan1 = new LinkMan();
        linkMan1.setLkm_name("cde");

        //設置關係
        linkMan1.setCustomer(customer1);
        customer1.getLinkMans().add(linkMan1);

        //只保存一個對象會報瞬時態異常的錯誤,保存後一方爲爲持久態對象,一個爲瞬時態對象
        session.save(linkMan1);
        session.save(customer1);
        tx.commit();
    }
    /*一對多的級聯操作
    *級聯:操作一個對象的時候。是否會同時操作其關聯的對象
    *
    * 級聯是有方向性的:
    *
    *
    * 級聯保存或更新
    * 級聯刪除
    * */



    /*級聯保存或更新
    * 保存客戶級聯聯繫人  :操作的主體是客戶,在Customer.hbm.xml配置客戶
    *
    * 途徑:通過配置   cascade  完成
    *    <set name="linkMans" cascade="save-update">
    * */
    @Test
    public void demo2(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Customer customer1 = new Customer();
        customer1.setCust_name("kevin");
        LinkMan linkMan1 = new LinkMan();
        linkMan1.setLkm_name("@kevin");

        //設置關係
        linkMan1.setCustomer(customer1);
        customer1.getLinkMans().add(linkMan1);

        session.save(customer1);
        tx.commit();
    }
    /*級聯保存或更新
   * 保存聯繫人級聯客戶  :操作的主體是客戶,在linkMan.hbm.xml配置客戶
   *
   * 途徑:通過配置   cascade  完成
   *    <set name="linkMans" cascade="save-update">
   * */
    @Test
    public void demo3(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Customer customer1 = new Customer();
        customer1.setCust_name("kevin");
        LinkMan linkMan1 = new LinkMan();
        linkMan1.setLkm_name("@kevin");

        //設置關係
        linkMan1.setCustomer(customer1);
        customer1.getLinkMans().add(linkMan1);

        session.save(linkMan1);
        tx.commit();
    }
    /*
    *測試對象的導航
    * 前提:一對多的雙方都設置了cascade="save-update"
    */
    @Test
    public void demo4(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        Customer customer = new Customer();
        customer.setCust_name("kevin");


        LinkMan linkMan1 = new LinkMan();
        linkMan1.setLkm_name("kevin1");
        LinkMan linkMan2 = new LinkMan();
        linkMan2.setLkm_name("kevin2");
        LinkMan linkMan3 = new LinkMan();
        linkMan3.setLkm_name("kevin3");

        //設置關係
        linkMan1.setCustomer(customer);
        customer.getLinkMans().add(linkMan2);
        customer.getLinkMans().add(linkMan3);

        //雙方都設置了cascade
       // session.save(linkMan1);//發送  4 條insert語句
        session.save(customer); //發送   3  條insert語句
        tx.commit();
    }
    /*級聯保存或更新
    *
    *刪除客戶級聯刪除聯繫人
    * 刪除聯繫人級聯刪除客戶:一般不用 先刪從表
    * */
    @Test
    public void demo5(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        //沒有級聯刪除,默認情況  會刪除客戶,修改聯繫人的外鍵
        /*  Customer customer = session.get(Customer.class,1l);
        session.delete(customer);*/

        //刪除客戶同時刪除聯繫人
        /*級聯刪除
        *   *刪除主體客戶
        *   * 途徑:通過配置   cascade  完成
        *    <set name="linkMans" cascade="save-update,delete">
        * */

        Customer customer = session.get(Customer.class,1l);
        session.delete(customer);

        tx.commit();
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章