org.hibernate.LazyInitializationException:无法初始化代理 – 没有Session,加载un fois
Foo看起来有这个:
@ManyToMany private Set favouritedBy;
用户有这个:
@ManyToMany(mappedBy = "favouritedBy") private Set favourites = new HashSet(); public Set getFavourites() { return favourite; }
并且fooService具有此function,通过tranactional方法在打开会话时访问lazyloaded集合:
@Transactional(readOnly = true) public Set getFavourites(User user) { user = dao.get(User.class, user.getId()); //the dao gets a session Set favourites = user.getFavourites();//but the session is not here and the exception is thrown? return favourties; }
编辑这个修复它,而不使用标准:
Set favourites = new HashSet(user.getFavourites());
这用标准修复了它
Session session = sessionFactory.getCurrentSession(); final Criteria crit = session.createCriteria(Foo.class); crit.setFetchMode("favourites", FetchMode.JOIN); crit.add(Property.forName("id").eq(id)); return (Foo) crit.uniqueResult();
ManyToMany
的默认FetchType
是LAZY
,用于处理惰性关联的hibernate文档明确地将这种访问称为错误。 只有在会话仍处于打开状态时,您才能与延迟关联的对象进行交互。 该部分文档还提供了访问对象的懒惰关联成员的替代方法。 我们更喜欢在我们的应用程序中使用的标准中将获取模式指定为JOIN
编辑 :
Set favourites = user.getFavourites();
上面的语句实际上并不返回包含所有Foo
对象的集合。 它只是一个代理。 仅当访问集合中的元素时才会获取实际的Foo
对象,如favorites.iterator()
等。此操作显然发生在getFavorites()
方法之外。 但getFavorites()
方法上的@Transactional
注释表明会话将在此方法结束时关闭。
因此,当在collections夹集上调用方法时,会话已经关闭,因此exception。
要解决此问题,您应该使用Criteria对象来检索用户并将获取类型指定为JOIN
以便在返回的User对象中填充Foo对象。
有两种解决方案。
-
不要使用延迟加载。
在XML中设置
lazy=false
或设置@OneToMany(fetch = FetchType.EAGER)
在注释中。 -
使用延迟加载。
在XML中设置
lazy=true
或在注释中设置@OneToMany(fetch = FetchType.LAZY)
。并在
web.xml
添加filter... hibernateFilter org.springframework.orm.hibernate4.support.OpenSessionInViewFilter sessionFactoryBeanName mySessionFactory hibernateFilter /* ...
是在applicationContext.xml
中定义的sessionFacory bean名称
是的,应该在跨国上下文中访问该对象,否则它将抛出一个LazyInitializationException
。