Hibernate 延遲載入原理

飄揚的紅領巾發表於2013-08-29

    如何簡單的理解延遲載入?開發中常見的org.hibernate.LazyInitializationException no session錯誤又是怎麼產生的?下面透過一個簡單的例子來解析一下。

load VS. get

    load是Hibernate利用延遲載入獲取物件的方法,當呼叫load時返回的是一個代理物件,並且該物件只包含主鍵ID。只有當你想主動獲取該物件的其他非主鍵屬性時,才會去資料庫中獲取對應的屬性返回。如果這時該物件對應的資料庫記錄被刪除了或不存在則會報丟擲ObjectNotFoundException異常。

    get是Hibernate獲取物件的一個普通方法,沒有使用延遲載入,呼叫get時hibernate直接返回資料庫中對應的記錄資訊。如果資料庫中不存在該物件的記錄,會丟擲空指標異常。

程式所示

load:

   1:  Session session = null;
   2:          try {
   3:              session = HibernateUtil.openSession();
   4:              //使用load,利用延遲載入獲取物件其他屬性
   5:              Object object = session.load(Member.class, 121L);
   6:              String mobile = ((Member) object).getMobile();//<---這裡當呼叫getMobile()時,才會去資料庫查詢對應的記錄
   7:              System.out.println(mobile);
   8:          } catch (HibernateException e) {
   9:              e.printStackTrace();
  10:          } finally {
  11:              if (session != null)
  12:                  session.close();
  13:          }

get:

   1:  Session session = null;
   2:          try {
   3:              session = HibernateUtil.openSession();
   4:              //使用get,直接從資料庫中查詢對應的記錄
   5:              Object object = session.get(Member.class, 121L);
   6:              String mobile = ((Member) object).getMobile();//<---這裡沒有使用延遲載入直接獲取mobile
   7:              System.out.println(mobile);
   8:          } catch (HibernateException e) {
   9:              e.printStackTrace();
  10:          } finally {
  11:              if (session != null)
  12:                  session.close();
  13:          }

使用延遲載入時,常見的org.hibernate.LazyInitializationException no session異常,又是怎麼產生的呢?

這是因為當使用延遲載入獲取物件屬性時如果這時session已經關閉,則無法進行資料庫操作,就會報出上述異常,我們用程式模擬一下:

get:

   1:  Session session = null;
   2:          try {
   3:              session = HibernateUtil.openSession();
   4:              //使用get,直接從資料庫中查詢對應的記錄
   5:              Object object = session.get(Member.class, 121L);
   6:              session.close();//這時關閉session
   7:              String mobile = ((Member) object).getMobile();//可以正常獲取,因為mobile是從物件中直接獲取的
   8:              System.out.println(mobile);
   9:          } catch (HibernateException e) {
  10:              e.printStackTrace();
  11:          } 

load:

   1:  Session session = null;
   2:          try {
   3:              session = HibernateUtil.openSession();
   4:              //使用get,直接從資料庫中查詢對應的記錄
   5:              Object object = session.load(Member.class, 121L);
   6:              session.close();//這時關閉session
   7:              String mobile = ((Member) object).getMobile();//使用load的情況,獲取mobile是從資料庫中查詢的,但此時session已經關閉,故呼叫getMobile時會丟擲org.hibernate.LazyInitializationException no session異常
   8:              System.out.println(mobile);
   9:          } catch (HibernateException e) {
  10:              e.printStackTrace();
  11:          } 

相關文章