2016-08-20 56 views
0

我叫刀從我的服務爲LazyInitializationException中在休眠:無法初始化代理 - 沒有會話

@Override 
@Transactional 
public Product getProductById(int id) { 
    return productDao.getProductById(id); 
} 

而在DAO我收到的產品爲

@Override 
public Product getProductById(int id) { 
    Product p = sessionFactory.getCurrentSession().load(Product.class, id); 
    System.out.print(p); 
    return p; 
} 

這將運行正常,但如果我更改我的dao類到

@Override 
public Product getProductById(int id) { 
    return sessionFactory.getCurrentSession().load(Product.class, id); 
} 

我得到org.hibernate.LazyInitializationException:無法初始化代理y - 沒有會話。在我剛剛打印產品的視圖層中發生異常。我不明白爲什麼在dao方法的同一行中返回導致視圖圖層中的異常,但如果將其保存在引用中然後返回它,則工作正常。

回答

1

以下是一個很好的reference,可讓您熟悉.get()和.load()方法的工作原理。

@Override 
public Product getProductById(int id) { 
    Product p = sessionFactory.getCurrentSession().load(Product.class, id); 
    return p; 
} 

session.load()默認情況下會返回一個代理對象而不會觸及數據庫。如果表中沒有任何記錄,它基本上會返回NoObjectFoundError,否則它將返回一個引用而不填充實際對象,甚至不會觸及數據庫。 您的上述方法返回代理,並且由於它也必須初始化您的對象,所以會話保持打開並且對象被填充。

@Override 
public Product getProductById(int id) { 
    return sessionFactory.getCurrentSession().load(Product.class, id); 
} 

但在你的第二種方法中,基本上是一個代理沒有任何初始化返回。會議之後沒有任何使用前關閉。因此你得到錯誤。

希望幫助

0

當你處理Hibernate和視圖層時,這是一個典型的問題。發生錯誤是因爲在呈現視圖之前Hibernate會話已關閉。解決這個問題的兩個最簡單的方法是使用Open Session In View模式,或者在視圖呈現之前獲取視圖中需要的所有數據。

由於您使用的春天,第一個解決方案是最簡單的一個 - 只要申請OpenSessionInViewFilter(或OpenEntityManagerInViewFilter如果你正在使用JPA):

http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter.html http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/jpa/support/OpenEntityManagerInViewFilter.html

你也應該讀哪些利弊和使用OSIV模式的缺點。

0

此錯誤意味着您試圖訪問一個懶洋洋地加載的屬性或集合,但Hibernate的Session被關閉或不可用。 在Hibernate中延遲加載意味着對象不會被填充(通過數據庫查詢),直到在代碼中訪問屬性/集合。 Hibernate通過創建一個動態代理對象來實現這一點,只有當您第一次使用該對象時纔會觸及數據庫。爲了這個工作,你的對象必須在整個生命週期中連接到一個開放的Hibernate會話。

如果您刪除SOP語句,那麼對象根本不被訪問,因此不會被加載。當你嘗試在代碼的其他部分代碼中訪問它時,它會拋出LazyInitializationException。

相關問題