org.hibernate.LazyInitializationException:懒惰初始化角色集合失败(Hibernate + Spring)
Posted
技术标签:
【中文标题】org.hibernate.LazyInitializationException:懒惰初始化角色集合失败(Hibernate + Spring)【英文标题】:org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role (Hibernate + Spring) 【发布时间】:2011-10-23 10:20:54 【问题描述】:我有一个带有以下文件的 SpringMVC+Hibernate Web 应用程序:
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="dsfa@efe45"/>
</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 类和映射应该没问题,我不会写(丢了行 :)) 所以问题是我得到了
org.hibernate.LazyInitializationException: 延迟初始化角色集合失败:orm.Document.uploadedDocumentsById,没有会话或会话关闭
controller.DocumentController 生成的页面刷新时。显然,缓存和事务存在我无法解决的问题。此外,使用 dao.DocumentViewDao 中的 all() 不会抛出这样的异常(但查询中没有 FETCH)。那么你有什么想法吗?我也很乐意收到有关此代码的任何 cmets 和/或建议以改进它(我是 Spring 和 Hibernate 的新手)。
【问题讨论】:
How to solve the “failed to lazily initialize a collection of role” Hibernate exception的可能重复 【参考方案1】:当返回实体实例的查询是可缓存的并且您有缓存命中时,缓存仅返回实体的 ID,然后使用会话加载实体.这意味着当您有缓存命中时,不再应用连接 fecth。这也意味着查询返回的所有实体实例也应该在二级缓存中,否则性能实际上可能比没有查询缓存时更差。
因此,您应该在 DAO 中使用 Hibernate.initialize(document.getUploadedDocumentsById()
以确保它已被初始化。
【讨论】:
哦,这很好用。但是每次我刷新页面时,都会对获取的实体进行查询...减少它会很好。以上是关于org.hibernate.LazyInitializationException:懒惰初始化角色集合失败(Hibernate + Spring)的主要内容,如果未能解决你的问题,请参考以下文章