hibernate讀書筆記-懶加載《-》

         懶加載是指程序推遲訪問數據庫,這樣作能夠保證有時候沒必要要的訪問數據庫,由於訪問一次數據庫是比較耗時的。
html

         1、load方法的懶加載java

         先看以下代碼段linux

[java] view plaincopyprint?web

<EMBED id=ZeroClipboardMovie_1 name=ZeroClipboardMovie_1 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=1&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">數據庫

  1. <span style="font-size:16px;">public class UserManager {  session

  2.   

  3.     public static void main(String[] args) {  app

  4.         Users user = new Users();  dom

  5.         user.setBirthday(new Date());  oop

  6.           

  7.         Name name = new Name();  fetch

  8.         name.setFirstName("guo");  

  9.         name.setLastName("zhao");  

  10.           

  11.         user.setName(name);  

  12.         addUser(user);  

  13.           

  14.         Users users = getUser(user.getId());  

  15.         System.out.println(users.getName());  

  16.           

  17.     }  

  18.       

  19.       

  20.     static Users getUser(int id){  

  21.         Session session = HibernateUtil.getSession();  

  22.         try {  

  23.             Users users = (Users) session.load(Users.class, id);  

  24.             return users;  

  25.         } finally{  

  26.             session.close();  

  27.         }  

  28.     }  

  29.       

  30.     static void addUser(Users users){  

  31.         Session session = null;  

  32.         Transaction tx = null;  

  33.           

  34.         try {  

  35.             session = HibernateUtil.getSession();  

  36.             tx = session.beginTransaction();  

  37.   

  38.             session.save(users);  

  39.             tx.commit();  

  40.         } catch (HibernateException e) {  

  41.             if (tx!=null) {  

  42.                 tx.rollback();  

  43.             }  

  44.             throw e;  

  45.         }finally{  

  46.             if(session!=null){  

  47.                 session.close();  

  48.             }  

  49.         }  

  50.     }  

  51. }</span>  


         上面代碼是先增長一個用戶、而後再查詢這個用戶的name組合屬性。運行上面的時候,該程序會拋出這樣一個異常:

Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session這就是懶加載不能初始化異常。其緣由就在於no session。在前面個持久化對象中已經說明:使用load方法時,該方法將具備延遲加載的功能,load方法並不會當即去訪問數據庫,它會返回一個代理對象,只有當你真正去訪問這個對象的時候,它纔會去訪問數據庫。

         經過上面的圖,咱們看出,hibernate根本就沒有select語句,也就是說hibernate沒有去訪問數據庫,因此這個時候你去訪問它確定是沒有的。但爲何沒有拋出空指針異常?沒有拋出空指針異常,也就是說明User對象是存在的,那它是什麼呢?經過輸出user.getClass()能夠看出是這樣一個東西:

         class com.hibernate.domain.Users_$$_javassist_5

         這個user就是load返回的代理對象。可是這個對象並非咱們所要的。咱們所要的是一個User實例對象。

         那麼怎麼解決這個問題呢?

         第一種方法:在關閉session以前訪問該對象

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_2 name=ZeroClipboardMovie_2 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=2&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. <span style="font-size:16px;">  static Users getUser(int id){  

  2.         Session session = HibernateUtil.getSession();  

  3.         try {  

  4.             Users users = (Users) session.load(Users.class, id);  

  5.             users.getName();  

  6.             return users;  

  7.         } finally{  

  8.             session.close();  

  9.         }  

  10.     }</span>  

         不過這句話看起來會很奇怪。咱們一般會採用以下的方式

[java] view plaincopyprint?

<EMBED id=ZeroClipboardMovie_3 name=ZeroClipboardMovie_3 type=application/x-shockwave-flash align=middle pluginspage=http://www.macromedia.com/go/getflashplayer height=14 width=29 src=http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf wmode="transparent" flashvars="id=3&width=29&height=14" allowfullscreen="false" allowscriptaccess="always" bgcolor="#ffffff" quality="best" menu="false" loop="false">

  1. <span style="font-size:16px;">  static Users getUser(int id){  

  2.         Session session = HibernateUtil.getSession();  

  3.         try {  

  4.             Users users = (Users) session.load(Users.class, id);  

  5.             Hibernate.initialize(users);  

  6.             return users;  

  7.         } finally{  

  8.             session.close();  

  9.         }  

  10.     }</span>  

         利用hibernate的initialize()方法將這個代理對象給初始化

         注:在使用代理對象的getId()方法和getClass()方法的時候,並不會拋出不能初始化異常,由於這兩個屬性並不用查詢數據庫。

 

         2、在缺省的狀況下,hibernate對於關聯關係會採用懶加載的方式。也就是說1-一、1-N、N-一、N-N都存在懶加載的問題。

           2.一、one-to-one懶加載

         一對一的懶加載並不經常使用,由於懶加載的目的是爲了減小與數據庫的交互,從而提升執行效率,而在一對一關係中,主表中的每一條數據只對應從表的一條數據庫,就算都查詢也不會增長多少交互的成本,並且主表不能有contrained=true,因此主表是不能懶加載的。可是從表能夠有。

         實現此種懶加載必須在從對象這邊同時知足三個條件:
            1lazy=falselazy的屬性有三個選項分別爲:no-proxyfalseproxy
            2Constrained = true 
            3fetch=select
         注:當fetch設置爲
join時,懶加載就會失效。由於fetch的做用是抓取方式,他有兩個值分別問selectjoin,默認值爲select。即在設爲join時,他會直接將從表信息以join方式查詢到而不是再次使用select查詢,這樣致使了懶加載的失效。

  

         2.二、one-to-many懶加載

         與one-to-one關聯不一樣,對one-to-many而言,主表的每一條屬性都會對應從表的多條數據,這個時候懶加載就顯得很是有效了。好比一個部門裏面有多個員工,若是沒有懶加載,每查詢這個部門的時候都會查詢出多個員工,這會大大增長與數據庫交互的成本。因此Hbernate默認的是加入懶加載的。這就是查詢集合屬性的時候返回的是一個PersistentIndexed*類型對象的緣由。該對象其實就是一個代理對象。固然,能夠在映射文件中經過將lazy屬性設爲假來禁用。

          Hibernate默認對one-to-many就是使用的懶加載,但用戶也能夠取消懶加載操做:
            一:設置lazy=」false」;
            二:設置fetch=」join」.
         實現此種懶加載必須在從對象這邊同時知足兩個個條件:
           1lazy=falselazy的屬性有三個選項分別爲:no-proxyfalseproxy
           2fetch=select

 

           2.三、mang-to-one懶加載

         此關聯關係的懶加載和one-to-one的懶加載同樣都是可要可不要的,由於對執行效率的提升都不是很是明顯。雖然多對一與一對一關係方式相同,可是在Hibernate中多對一時,默認是進行懶加載的。另外有一點須要注意的是懶加載並不會區分集合屬性裏面是否有值,即便是沒有值,他依然會使用懶加載

         實現此種懶加載必須在從對象這邊同時知足兩個個條件:
             1lazy=falselazy的屬性有三個選項分別爲:no-proxyfalseproxy
             2fetch=select

 

         2.四、many-to-many懶加載

         此關聯關係的懶加載和one-to-many的懶加載同樣對程序的執行效率的提升都是很是明顯的。
         實現此種懶加載必須在從對象這邊同時知足兩個個條件:
            1lazy=falselazy的屬性有三個選項分別爲:no-proxyfalseproxy
             2fetch=select

         可以懶加載的對象都是被改過的代理對象,當相應的對象沒有關閉時,訪問這些懶加載對象的屬性(getId和getClass除外)hibernate會初始化這些代理,或用hibernate.initalize(proxy)來初始化代理對象;當關閉session後在訪問懶加載的對象就會出現異常

相關文章
相關標籤/搜索