Hibernate 一對多,多對多,多對一檢索策略


一.概述

    我們先來談談檢索數據時的兩個問題:

     1.不浪費內存   2.更好的檢索效率

     以上說的問題都是我們想要避免的,接下來就引出了我們要討論的話題---------------hibernate檢索策略

二.hibernate檢索策略分為三種:

     1.類級別的檢索策略

     2.一對多和多對多檢索策略

     3.多對一和一對一關聯的檢索策略

  (1)類級別的檢索策略分為立即檢索和延遲檢索,默認為延遲檢索。

         立即檢索:立即加載檢索方法指定的對象,立即發送SQL.

         延遲檢索:延遲加載檢索方法指定的對象,在使用具體的對象時,再進行加載,發送SQL.

   lazy有兩個取值:false(立即加載) 和 true(延遲加載)

  討論一:當用get()方法檢索數據時,在類級別檢索策略不管是不是延遲加載都會立即檢索

  接下來看看代碼實現是不是跟我說的一樣:

  配置文件中:

 

測試類代碼:

 @Test
    public void select1(){
        Session session = HibernateUtil.currentSession();
        Transaction tx = session.beginTransaction();
        House house = session.get(House.class, 1);
        System.out.println("===========================");
       // System.out.println(house.getType().getName());
        tx.commit();
        HibernateUtil.closeSession();
    }

 

  接下來看看測試的效果:

 

接下來我們把lazy設為true:

效果:

大家注意沒,測試類有一行代碼我是注釋掉的,為的就是讓我們很好的理解,如果我把下面的代碼放開是什么效果呢?大家要注意現在我們的查詢是get()方法:

我們得到的結果是一樣的,這樣就說明了當使用類級別檢索時,使用get()方法都會立即加載。

討論二:我們在來看看load()方法(也是類級別的檢索),我們只需要修改代碼即可:

   @Test
    public void select1(){
        Session session = HibernateUtil.currentSession();
        Transaction tx = session.beginTransaction();
        House house = session.load(House.class, 1);
        System.out.println("=========lazy:false==================");
        //System.out.println(house.getType().getName());
        tx.commit();
        HibernateUtil.closeSession();
    }

lazy:false時

我們把lazy設為true時效果如下:

我們看到只打印了分割線,到這里我們可以看出get()和load()方法在類級別檢索時的區別,接下來我們看看當放開注釋的代碼時會發生什么呢?

我們可以很直觀的看出來,得到的結果不一樣,當延遲加載的情況下,當我們有后續操作時才會向數據庫發送SQL,查詢結果。而立即加載在我們有后續操作之前,已經先查詢了一道,然后再根據后續操作查詢結果。

通過以上我們做的測試,我們可以得出一個結論:

當類級別檢索時:get()方法不管延遲加載還是延遲加載都會先查詢一道,有后續操作再向數據庫發送SQL,得到結果。

                       load()方法:當是延遲加載的情況下,有后續操作才會向數據庫發送SQL,查詢結果。

                                        當是立即加載的情況下,就和get()方法一樣,先查詢一道,有后續從操作在查詢。

總的來說,load()方法受類級別檢索策略影響,get()方法不受影響。

  (2)一對多和多對多檢索策略

 在映射文件中,用<set>元素來配置一對多和多對多關聯關系

lazy取值有:false(立即加載),true(延遲加載)和extra(加強延遲加載)

配置文件:

測試類代碼:

 @Test
    public void select(){ Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); House house = session.load(House.class, 1); System.out.println("==========lazy:false==================="); System.out.println(house.getClass()); // System.out.println(house.getTitle());  tx.commit(); HibernateUtil.closeSession(); }

 先來看看當我們使用load()加載數據時,我們輸出的結果:

當lazy取值為false:

當lazy取值為true:

都沒有后續操作時,沒有不同。接下來我們看一下當有后續操作時(解開注釋的代碼),會發生什么?

lazy:true時:

lazy為false時: 

 

 我們可以明顯的看出這兩個的不同,延遲加載時發送了一條SQL,立即加載時發送了兩條SQL,延遲加載的后續操作是根據你的條件查詢的,立即加載根據你的條件查詢之后,如果有與之相關的表,也會進行兩表查詢。

get()方法獲取時,沒有后續操作:

lazy:true

lazy:false:

 

當有后續操作時,看看是什么情況?

lazy:true時,

lazy:false時,

由此可以看出,當使用get()方法時,不管有沒有后續操作,都會先向數據庫發送SQL語句,保存對象的信息,而且我們也看出來不管load()和get()在立即加載情況下,會向數據庫發送SQL,根據你查詢對象所關聯的表的個數來決定向數據庫發送幾條SQL語句,(我列舉的例子是發送兩條)。

當lazy取值為extra(加強延遲加載),接下來的測試,我們主要探討的是獲取集合的size()時有什么不同:

配置文件:

測試類代碼:

 @Test
    public void select(){
        Session session = HibernateUtil.currentSession();
        Transaction tx = session.beginTransaction();
        Users users = session.get(Users.class, 2);
        System.out.println("==========lazy:true===================");
        System.out.println(users.getClass());
        //System.out.println(users.getHouse().size());
        tx.commit();
        HibernateUtil.closeSession();
    }

 

先來探討沒有后續操作時,get()和load()方法

get()方法:

load()方法:

當有后續操作時,get()和load()方法的結果:

get()方法:

load()方法:

當有后續操作時,get()和load()方法向數據庫索要數據的語句相同。不同的是get()方法不管有沒有后續操作都會向數據庫發送SQL,

而load()方法是在你用到它的屬性的時候才會向數據庫發送SQL。

最后看一下當取值為true 和 false時語句有什么不同?

在延遲加載的情況下:

get()方法獲取數據                                             load()方法獲取數據

 

在立即加載的情況下:

get()方法加載數據:                                                 load()方法加載數據:

這里寫的可能有點啰嗦了,但是總的一句話:

Extra:極其懶惰,只有訪問集合對象的屬性時才會加載,訪問集合本身的屬性時(例如,集合大小,生成count),不會立即加載。

最后來給大家總結一下:

 類級別檢索策略:僅僅適用於load()加載

好了,就討論到這里吧,可能我寫的也不是太好,這就需要自己下來多多練習,熟練實踐.......

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM