Hibernate懶加載

1. 懶加載概述以及使用情景

描述:懶加載(lazy),簡單說就是延時、延遲加載。 
情景:在Hibernate框架應用中,就是當我們要訪問的數據量過大時,使用緩存並不太合適,因爲內存容量有限 ,爲了減少系統資源的消耗,減少併發量,這時需要用懶加載機制來彌補這種缺陷,但是這並不意味用了懶加載總體性能就提高了。 
應用: 
比如學校school和學生student,學校與學生1對多,如果lazy設置爲 false,那麼只要加載了一個學校的信息,就會根據一對多配置的關係把所有學生的信息也加載出來。但是實際上有時候只是需要用到學校的信息,不需要用到 學生的信息,這時學生信息的加載就等於浪費資源。如果lazy設置爲true,那麼只有當你訪問學校信息的學生信息時候纔會去加載學生的信息的信息。

2. 懶加載的原理 
在Hibernate中運用session進行查詢時,有get()和load()兩個方法,先說一下兩者的區別: 
這兩種方法的不同就是load()擁有懶加載的特性。Load()方法就是在查詢某一條數據的時候並不會直接將這條數據以指定對象的形式來返回,而是在你真正需要使用該對象裏面的一些屬性的時候纔會去數據庫訪問並得到數據。他的好處就是可以減少程序本身因爲與數據庫頻繁的交互造成的處理速度緩慢。 
* session.get() 
* 1、方法加載出來的對象是class對象 
* 2、在session.get方法執行的時候發出sql語句 
* 3、class對象是有值的 
* session.load () 
* 1、方法加載出來的對象是class的代理對象 
* 2、在加載其屬性的時候發出sql語句(按照需求加載,延遲加載) 
* 3、獲取標識符(UUID)屬性是不用延遲加載的,獲取普通屬性是需要發出sql語句的 
在此以User類爲例

    public static void query(int id){
           Session session=null;
            try{
                session=HibernateUtil.getSession();
                User user=(User) session.load(User.class, id);
                //System.out.println(user.getName());
                System.out.println(user.getClass());
            }catch(HibernateExceptionex){
                ex.printStackTrace();
            }finally{
                if(session!=null){
                   session.close();
                }
            }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
運行上述方法後,我們並沒有看到Hibernate打印任何查詢語句,當將註釋的語句打開,可以查詢到的User的name。這時我們可以看到Hibernate產生的查詢語句並看到user的name屬性。這就是懶加載了。

3.懶加載代理對象

通過打印user.getClass()方法來驗證,打印出來的結果並不是null,其實是代理對象,而這個對象所屬的類是User類的子類,是Hibernate自動實現的一個子類。 
代理對象的生命週期是什麼呢?

    public static User query(int id){
           Session session=null;
           User User=null;
            try{
                session=HibernateUtil.getSession();
                User=(User)session.load(User.class, id);
                //System.out.println(User.getName());
            }catch(HibernateExceptionex){
                ex.printStackTrace();
            }finally{
                if(session!=null){
                   session.close();
                }
            }
            return User;
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//會拋出一個org.hibernate.LazyInitializationException異常 
這說明懶加載的時候如果想通過代理對象查詢數據庫,需要在該session關閉以前纔可以。但如果一定要在session關閉以後再使用代理對象的話,Hibernate中定義了一個初始化代理對象的方法initialize(),通過該方法即可將代理對象初始化。

4. 懶加載功能實現總結 
1.通過Session.load()實現懶加載

load(Object, Serializable):根據id查詢 。查詢返回的是代理對象,不會立刻訪問數據庫,是懶加載的。當真正去使用對象的時候纔會訪問數據庫。 
用load()的時候會發現不會打印出查詢語句,而使用get()的時候會打印出查詢語句。 
使用load()時如果在session關閉之後再查詢此對象,會報異常:could not initialize proxy - no Session。處理辦法:在session關閉之前初始化一下查詢出來的對象:Hibernate.initialize(user);

使用load()可以提高效率,因爲剛開始的時候並沒有查詢數據庫。但很少使用。

2.one-to-one(元素)實現了懶加載。

在一對一的時候,查詢主對象時默認不是懶加載。即:查詢主對象的時候也會把從對象查詢出來。

需要把主對象配製成lazy=”true” constrained=”true” fetch=”select”。此時查詢主對象的時候就不會查詢從對象,從而實現了懶加載。

一對一的時候,查詢從對象的是默認是懶加載。即:查詢從對象的時候不會把主對象查詢出來。而是查詢出來的是主對象的代理對象。

3.many-to-one(元素)實現了懶加載。

多對一的時候,查詢主對象時默認是懶加載。即:查詢主對象的時候不會把從對象查詢出來。

多對一的時候,查詢從對象時默認是懶加載。即:查詢從對象的時候不會把主對象查詢出來。

hibernate3.0中lazy有三個值,true,false,proxy,默認的是lazy=”proxy”.具體設置成什麼要看你的需求,並不是說哪個設置就是最好的。在與標籤上:當爲true時,會有懶加載特性,當爲false時會產生N+1問題,比如多個學生對應一個班級,當查詢班級信息時也會查詢該班級學生的信息

lazy= 什麼時候捉取

fetch= 捉取方式:select=關聯查詢;join=連接表的方式查詢(效率高)

fetch=join時,lazy的設置將沒有意義. 
4. one-to-many(元素)懶加載:默認會懶加載,這是必須的,是重常用的。

一對多的時候,查詢主對象時默認是懶加載。即:查詢主對象的時候不會把從對象查詢出來。

一對多的時候,查詢從對象時默認是懶加載。即:查詢從對象的時候不會把主對象查詢出來。

需要配置主對象中的set集合lazy=”false” 這樣就配置成是不懶加載了。或者配置抓取方式fetch=”join”也可以變成不懶加載。
--------------------- 

原文:https://blog.csdn.net/heart_2015/article/details/51331948?utm_source=copy 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

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