2011-06-11 137 views
0

我有一個hibernate DAO,當試圖訪問一個包/集合的返回對象的成員時拋出一個「無法懶惰地初始化一個角色集合」異常。保持Hibernate會話通過註釋失效? - 未能懶洋洋地初始化一個角色集合

我明白拋出異常的問題的範圍。 Hibernate返回我的對象​​,並且對於任何集合,返回代理對象。在我的調用者中,當我去訪問這些代理對象時,因爲休眠會話已經過期,這個異常被拋出。

我想知道的是,如何使用註釋保持會話從到期?可能嗎?

舉例來說,如果我的調用方法:

@RequestMapping("refresh.url") 
public ModelAndView refresh(HttpServletRequest request, HttpServletResponse response, int id) throws Exception { 
    TestObject myObj = testObjDao.get(id); 
    // throws the exception 
    myObj.getCollection(); 

我將如何防止使用註解這個異常?我知道有一個解決辦法是通過回調這僞代碼可能看起來像延長Hibernate的Session:

@RequestMapping("refresh.url") 
public ModelAndView refresh(HttpServletRequest request, HttpServletResponse response, int id) throws Exception { 
    session = get hibernate session... 
    session.doInSession(new SessionCallback() { 
     TestObject myObj = testObjDao.get(id); 
     // no longer throws the exception 
     myObj.getCollection(); 
    }); 

但這似乎相當重複的有在我所有的功能需要訪問集合。是不是有一種方法可以在那裏簡單地拍@Transactional註釋並完成它?如在:

@RequestMapping("refresh.url") 
@Transactional // this doesn't extend the session to this method? 
public ModelAndView refresh(HttpServletRequest request, HttpServletResponse response, int id) throws Exception { 
    TestObject myObj = testObjDao.get(id); 
    // throws the exception 
    myObj.getCollection(); 

感謝您的幫助,向我解釋這一點。

回答

0

我使用的解決方案是在DAO中的集合上使用@LazyCollection註釋。

@OneToMany(mappedBy = "<something here>", cascade = CascadeType.ALL) 
@LazyCollection(LazyCollectionOption.FALSE) 
1

你需要做到以下幾點:

1)讓Spring管理事務:

你可以閱讀更多關於它在這裏: http://www.mkyong.com/spring/spring-aop-transaction-management-in-hibernate/

這裏:

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative

2)現在懶惰加載:

當你從Hibernate獲取對象時,它的所有惰性關聯都作爲代理返回,然後當你訪問代理類時,你會得到異常,因爲你的Hibernate會話是關閉的。

解決方案是在視圖過濾器/攔截器中使用打開的會話。

http://www.paulcodding.com/blog/2008/01/21/using-the-opensessioninviewinterceptor-for-spring-hibernate3/

它看起來完全一樣:

<mvc:interceptors> 
<bean class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor"> 
<property name="sessionFactory"> 
<ref local="sessionFactory"/> 
</property> 
</bean> 
</mvc:interceptors> 

希望它能幫助。

1

休眠會話與網絡會話不同,它們不會過期。他們通過代碼或基礎設施手動關閉(例如Spring)。

在你的情況是不清楚你的會議是如何創建的第一個地方,因爲如果你輸入DAO沒有會話,你會得到完全不同的例外(No Session Bound to Thread)。所以,不知怎的,你的會話被創建並關閉。我的猜測是你的DAO通過@Transactional或通過攔截器進行交易,所以會話在你輸入時啓動,當你退出DAO方法時會關閉。在這種情況下,只要將DAO上的事務傳播設置爲PROPAGATION_REQUIRED,就可以將@Transactional放在您的MVC方法上。

但請記住,除了通過@Transactional註釋的方法之外,您不能攜帶您的收藏。例如,你不應該把它放在http會話中。如果這是一項要求,您可能需要考慮特殊的DTO對象來複制數據。

相關問題