LazyInitializationException: 延迟初始化角色集合失败 无法初始化代理 - 没有会话
Posted
技术标签:
【中文标题】LazyInitializationException: 延迟初始化角色集合失败 无法初始化代理 - 没有会话【英文标题】:LazyInitializationException: failed to lazily initialize a collection of role could not initialize proxy - no Session 【发布时间】:2015-04-01 21:51:39 【问题描述】:这在 SO 中被多次询问。但是他们没有解决我的问题,所以再次发布。
尝试访问我的应用程序时出现以下异常
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.wpt.models.Item.itemCategory, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:294)
at org.apache.taglibs.standard.tag.common.core.ForEachSupport.toForEachIterator(ForEachSupport.java:348)
at org.apache.taglibs.standard.tag.common.core.ForEachSupport.supportedTypeForEachIterator(ForEachSupport.java:224)
at org.apache.taglibs.standard.tag.common.core.ForEachSupport.prepare(ForEachSupport.java:155)
at javax.servlet.jsp.jstl.core.LoopTagSupport.doStartTag(LoopTagSupport.java:256)
web.xml
<filter>
<filter-name>HibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>hibernate4AnnotatedSessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
弹簧配置:
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"
p:sessionFactory-ref="hibernate4AnnotatedSessionFactory">
</bean>
Item.java
@Entity
@Table(name="item")
public class Item
@OneToMany(mappedBy="item", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private List<ItemCategory> itemCategory = new ArrayList<ItemCategory>();
ItemServiceImpl.java
@Override
@Transactional(readOnly=true)
public List<Item> getItemsByCategory(int categoryId)
return itemDAO.getItemsByCategory(categoryId);
在所有博客中,建议要么使用EAGER
fetch,要么使用OpenSessionInViewFilter
支持@Transactional
。
如果我使用EAGER
fetch,它会起作用。但不是以另一种方式工作。我已经使用@Transactional
注释实现了所有服务方法。我在这里犯了什么错误?有人可以帮忙吗?
【问题讨论】:
【参考方案1】:使用下面的过滤器代替 HibernateFilter
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
希望对你有所帮助。
【讨论】:
我不认为这是问题所在。它只是用户定义的过滤器名称。它可以是任何东西。这个问题已经解决了,我已经给出了答案。 这是由于错过了将 contextConfigLocation 初始化为 DispatcherServlet。一旦我初始化它就解决了。【参考方案2】:首先,您已经意识到如果您急切地提取会发生什么。这意味着当您请求项目时,对数据库的查询总是会带来 itemCategory。也许这不是您所期望的行为。
二、lazyInitialization异常是因为你在关闭会话后试图访问对象itemCategory。我想当您从方法“getItemsByCategorymethod”收到列表时会话已关闭。
我通常解决这种情况的方法(不是急切获取)有两种方法:
在关闭会话之前选择 itemCategory。无论你在哪里调用来执行查询,你都应该可以说List listItemCategroy = item.getItemCategory()
。
将 fetch.JOIN 添加到表 itemCategory 中,它将带来 ItemCategory。
如果你想避免这个错误,你可以在你的代码中添加这个:
if (Hibernate.isInitilized())
....
如果对象已初始化则返回 true,否则返回 false。
【讨论】:
是的,我注意到了。但是 fatch.JOIN 和 FetchType.EAGER 不一样?对不起,我在这方面有点困惑。你能给我一个详细解释的参考吗? (我浏览了一些链接,但细节还不够) 如果您在实体中指明 FetchType.EAGER,它将与您从数据库中检索的所有项目对象有关。但是,如果您的关系是惰性的并在条件中指示 fetch.JOIN,那么您只是说该查询使关系急切。认为您在请求项目时并不总是需要 itemCategory。假设您只需要 item_pk 作为列表,您是否还需要检索 itemCategory 对象?【参考方案3】:contextConfigLocation 用于指示 xml 文件(例如 Spring、spring-security)所在的位置。
懒惰的问题对我来说对 Spring 配置没有任何意义。
你能详细解释一下吗?
【讨论】:
是的,我也明白这一点。我认为当我们使用 OpenSessionInViewFilter 时,DispatcherServlet 能够识别 Spring 配置文件中的 sessionFactoryBean,只是我们通过它的 init-param 对其进行初始化。对此做一些分析。一旦找到它发生这种情况的正当原因,就会发布它。【参考方案4】:好的,经过一番努力,我终于想出了解决这个问题的办法。
在我将contextConfigLocation
添加到DispatcherServlet's <init-param>
后问题得到解决。更改后,我的DispatcherServlet
配置如下所示。
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
参考:This post
【讨论】:
以上是关于LazyInitializationException: 延迟初始化角色集合失败 无法初始化代理 - 没有会话的主要内容,如果未能解决你的问题,请参考以下文章