2011-08-09 95 views
2

我有以下文件用SpringMVC一個+ Hibernate的Web應用程序:org.hibernate.LazyInitializationException:無法初始化懶洋洋角色的集合(休眠+春)

的applicationContext.xml

<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="org.postgresql.Driver"/> 
    <property name="url" value="jdbc:postgresql://localhost:5432/db"/> 
    <property name="username" value="kjhkjkj"/> 
    <property name="password" value="[email protected]"/> 
</bean> 

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="hibernateSessionFactory"/> 
</bean> 

<bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
    <property name="transactionManager" ref="txManager"/> 
    <property name="transactionAttributes"> 
     <props> 
      <prop key="*">PROPAGATION_REQUIRED</prop> 
     </props> 
    </property> 
    <property name="target"> 
     <bean class="dao.DocumentViewDao"> 
      <property name="sessionFactory" ref="hibernateSessionFactory"/> 
     </bean> 
    </property> 
    <property name="proxyTargetClass" value="true"/> 
</bean> 

<bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
    <property name="dataSource" ref="dataSource"/> 
    <property name="mappingResources"> 
     <list> 
    <value>orm/Document.hbm.xml</value> 
    <value>orm/UploadedDocument.hbm.xml</value> 
    <!-- More resource files go here --> 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
     <value> 
      hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect 
      hibernate.show_sql = true 
      hibernate.format_sql = true 
      hibernate.generate_statistics = true 
      hibernate.cache.use_query_cache = true 
      hibernate.cache.use_second_level_cache = true 
      hibernate.cache.provider_class = org.hibernate.cache.EhCacheProvider 
      hibernate.query.substitutions = true 't', false 'f' 
     </value> 
    </property> 
</bean> 

<bean id="documentViewDao" class="dao.DocumentViewDao"> 
    <property name="sessionFactory" ref="hibernateSessionFactory"/> 
</bean> 

dao.DocumentViewDao

@Transactional 
public class DocumentViewDao extends HibernateDaoSupport 
{ 
public List all () 
     throws HibernateException 
{ 
    Session session = this.getSessionFactory ().getCurrentSession (); 

    return session.createQuery (new StringBuilder (35) 
        .append ("SELECT d.id AS id, d.identifier AS identifier, d.title AS title, u.version AS version, u.effectFrom AS effectFrom ") 
        .append ("FROM Document AS d ") 
        .append ("LEFT OUTER JOIN d.uploadedDocumentsById AS u ") 
        .append ("WITH u.isCurrent = true") 
        .toString ()) 
      .setCacheable (true) 
      .setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP) 
      .list (); 
} 

public Document getDocument (int documentId) 
     throws HibernateException 
{ 
    Session session = this.getSessionFactory ().getCurrentSession (); 

    Document document = null; 

    Query q = session.createQuery ("FROM IsoDocument AS d " + 
            "LEFT OUTER JOIN FETCH d.uploadedDocumentsById " + 
            "WHERE d.id = :documentId" 
    ); 
    q.setParameter ("documentId", documentId); 
    q.setCacheable (true); 
    document = (Document) q.uniqueResult (); 

    return document; 
} 
} 

controller.DocumentController

public class DocumentController implements Controller 
{ 
    public ModelAndView handleRequest (HttpServletRequest request, HttpServletResponse response) 
      throws Exception 
    { 
     ModelAndView modelAndView = new ModelAndView ("document"); 

     WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext (); 
     DocumentViewDao documentViewDao = (DocumentViewDao) context.getBean ("transactionProxy"); 

     Document document = DocumentViewDao.getDocument (Integer.parseInt (request.getParameter ("id"))); 
     modelAndView.addObject ("document", document); 

     return modelAndView; 
    } 
} 

的ORM類和映射應該OK,我就不會去寫(丟失的行:)) 所以,問題是我得到

org.hibernate.LazyInitializationException:無法延遲初始化角色集合:orm.Document.uploadedDocumentsById,沒有會話或會話關閉

當controller.DocumentController生成的頁面被刷新時。很明顯,我無法解決的緩存和交易存在問題。而且,使用dao.DocumentViewDao中的all()不會拋出這樣的異常(但查詢中沒有FETCH)。那麼你有什麼想法嗎?我也很樂意對這些代碼進行評論和/或建議,以提高它(對Spring和Hibernate來說是新的)。

回答

4

當查詢返回的實體實例是可緩存的並且您有緩存命中時,緩存只返回實體的ID,然後會話用於加載實體)。這意味着當您有緩存命中時,連接fecth不再適用。這也意味着查詢返回的所有實體實例也應該位於二級緩存中,否則性能實際上可能會比沒有查詢緩存時更差。

因此,您應該在DAO中使用Hibernate.initialize(document.getUploadedDocumentsById()以確保它已初始化。

+0

哦,這完美的作品。但每次刷新頁面時,都會提取查詢到的實體...將會很好地減少它。 –

相關問題