2013-02-06 24 views
1

我得到了着名的LazyInitializationException。Hibernate初始化不同事務中的對象

我有一個對象存儲在會話中的用戶。該對象包含一個懶惰初始化的其他對象Market。 當我在會話中加載用戶時,我不加載Market,因爲它太重了,我不需要它每次。

當我想加載市場時,我處於不同的事務中,我不想從數據庫中重新加載用戶。我如何檢索市場對象?知道User.market包含Hibernate代理,所以市場的id,我不想用反射破解Hibernate。

如果我可以在沒有加載到用戶的情況下加載市場,情況會更好。由於用戶在會話中,我不想在會話中放置很多東西。

JPA兼容解決方案會更好。

乾杯

回答

1

你必須做的是註解訪問者而不是字段。這將允許您在最初加載用戶時避免加載市場對象,但是您將可以從Hibernate代理對象訪問市場ID,而不會觸發延遲加載或獲取LazyInitializationException。然後,當你想要加載市場時,你會根據它的id做一個正常的實體檢索。您可以閱讀關於這項工作的詳細說明here

+0

完美,謝謝。 – tibo

1

如果關係是雙向的,那麼你可以使用獨立與像where market.user.id = ?子句的查詢加載市場。

+0

看到我對ring0的評論回答。這確實是一個解決方案,但這並不能滿足我:( – tibo

2

如果急於模式抓取是不能接受的,並且如果該事務不能被保持到市場檢索,特定道的方法可以被實現爲從用戶

public List<Market> retrieveMarketFromUser (final User user) { 
    Query query = session.createQuery("SELECT m FROM User AS u INNER JOIN u.market as m WHERE u.userid = :uid"); 
    query.setParameter("uid", user.getId()); 
    List<Market> list = query.list(); 
    return list; 
} 

或具體檢索市場短版

Query query = session.createQuery("SELECT u.market FROM User AS u WHERE u.userid = :uid"); 

這可能不是您期待的JPA解決方案,只是一種解決方法。

+0

我確實認爲這是我迄今發現的唯一與JPA兼容的解決方案。但是,我用這個解決方案得到的問題是一樣的,它避免了我重新加載用戶:我不想做一個涉及用戶表的查詢,因爲這個表是巨大的,而市場只有4行...謝謝,即使它不能解決我的問題,+1 – tibo

-1

既然你提到新的事務,那麼你可能會與屬於線程一個新的Hibernate Session工作,

使用此櫃面直接互動與Hibernate的Session

obj = session.merge(obj); 

如果您使用JPA2 Api

obj= entityManager.merge(obj); 

請評價答案,如果有幫助。 乾杯

+0

In我的問題是:「我不想從數據庫中重新加載用戶」,因爲你希望我評價你的答案...... – tibo

1

爲什麼顯而易見的解決方案不好?類似ring0建議的那樣,或者只需使用findByIdfind方法(如果User對象中已有該ID)。

//if using a session factory 
session.findById(Market.class, marketId); 

//if using the EntityManager 
em.find(Market.class, marketId); 

根據如何配置current_session_context_class(我有它在hibernate.cfg.xml)則可能是每一個新的事務一個新的會話。如果是這種情況,你不必擔心把太多東西放在那裏。您可以在關聯會話here中找到更多信息。

+0

對於誤解,我正在談論HTTP會話!用戶確實包含市場ID但是在hibernate代理對象中,我想我可以通過執行如下操作來獲取id: '((HibernateProxy)user.getMarket())。getHibernateLazyInitializer()。getIdentifier()' 即使t不是JPA兼容的,到目前爲止,這是我最好的解決方案。 – tibo

+0

這是正確的,你應該能夠用一個類似的語法(只要你有用戶對象)簡單地得到id:user.getMarket().getId()。 – Atticus