Java org.hibernate.LazyInitializationException:无法初始化代理-无会话,encore un fois
Foo looks中包含以下内容:Java org.hibernate.LazyInitializationException:无法初始化代理-无会话,encore un fois,java,spring,hibernate,Java,Spring,Hibernate,Foo looks中包含以下内容: @ManyToMany private Set<User> favouritedBy; manytomy中的默认值是LAZY,而的hibernate文档清楚地将这种访问称为错误。您只能在会话仍处于打开状态时与延迟关联的对象进行交互。文档的这一部分还提供了访问对象的此类延迟关联成员的替代方法。在我们的应用程序中,我们更愿意在所使用的条件中将获取模式指定为JOIN 编辑: Set<Foo> favourites = user.getFav
@ManyToMany
private Set<User> favouritedBy;
manytomy
中的默认值是LAZY
,而的hibernate文档清楚地将这种访问称为错误。您只能在会话仍处于打开状态时与延迟关联的对象进行交互。文档的这一部分还提供了访问对象的此类延迟关联成员的替代方法。在我们的应用程序中,我们更愿意在所使用的条件中将获取模式指定为JOIN
编辑:
Set<Foo> favourites = user.getFavourites();
Set favorites=user.getfavorites();
上面的语句实际上并没有返回包含所有Foo
对象的集合。它只是一个代理。实际的Foo
对象只有在访问集合中的元素(如favorites.iterator()
等)时才会被提取,此操作显然发生在getFavorites()方法之外。但是getFavorites()
方法上的@Transactional
注释表明会话将在该方法结束时关闭
因此,当对收藏夹集调用方法时,会话已经关闭,因此出现异常
为了解决这个问题,您应该使用Criteria对象来检索用户,并将获取类型指定为JOIN
,以便在返回的用户对象中填充Foo对象。是,应该在事务上下文中访问对象,否则操作将抛出一个lazyiinitializationexception
有两种解决方案
不要使用延迟加载
在XML中设置lazy=false
,或者在注释中设置@OneToMany(fetch=FetchType.EAGER)
使用延迟加载
在XML中设置lazy=true
,或在注释中设置@OneToMany(fetch=FetchType.lazy)
并在web.xml
<listener>
...
</listener>
<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>mySessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
...
</servlet>
...
冬眠过滤器
org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
sessionFactoryBeanName
mySessionFactory
冬眠过滤器
/*
...
而mySessionFactory
是您在applicationContext.xml
中定义的sessionFacory bean名称,如果您使用了@…中的任何一个。。。关系以及获取类型“Lazy”
<listener>
...
</listener>
<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>mySessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
...
</servlet>
而且你会得到LazyInitializationException-
这意味着你关掉了OpenInView,这很好
要避免两者懒散初始化异常
以及打开OIV(这使得Hibernate会话打开的时间比大多数情况下需要的时间更长)-
确保在发布列上指定了@Fetch(FetchMode.JOIN)。
例如:
之前:
@ManyToMany(fetch=FetchType.LAZY)
私人设置桶;
之后:
@Fetch(FetchMode.JOIN)
@ManyToMany(fetch = FetchType.LAZY)
private Set<Kek> keks;
@Fetch(FetchMode.JOIN)
@ManyToMany(fetch=FetchType.LAZY)
私人设置桶;
通过这种方式,您将强制连接获取类型,该类型将(非常简单地说)提供正确的查询,并连接所需的链接实体,不强制您使用即时获取。您确定您在spring上下文中设置了transactionManager
并定义了tx:annotation-driven
吗?是的,其他地方一切正常……您能在此处发布堆栈跟踪吗?我们将检查是否存在事务处理代码是的,我认为会话仍然处于打开状态,尽管这是问题所在,因为该方法是事务性的,并且使用已将会话注入其中的dao。当您的延迟关联集被复制以供调用getFavorites()
方法的调用方使用时,会话将已关闭,因为事务的范围在getFavorites()
方法的末尾结束。我一点也不明白。“事务的作用域在getFavorites()的结尾处结束”这就是我希望它结束的时候,我调用了user.getFavorities。会话打开时,它将从db加载数据并填充哈希集?(显然不是,我错了,我有时希望我从来没有为hibernate烦恼过)请看我试图解释到底发生了什么的更新。我可以只做“Set favorites=new HashSet(user.getfavorites());”这篇文章讨论了这些建议的解决方案:OpenInView是一个糟糕的解决方案,在其他任何可用的解决方案之前都是第一个。在这个反模式出现之前,我们应该使用更多的方法来解决这个问题
Set<Foo> favourites = user.getFavourites();
<listener>
...
</listener>
<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>mySessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
...
</servlet>
@ManyToMany(fetch = FetchType.LAZY)
private Set<Kek> keks;
@Fetch(FetchMode.JOIN)
@ManyToMany(fetch = FetchType.LAZY)
private Set<Kek> keks;