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的默认FetchTypeLAZY ,用于处理惰性关联的hibernate文档明确地将这种访问称为错误。 只有在会话仍处于打开状态时,您才能与延迟关联的对象进行交互。 该部分文档还提供了访问对象的懒惰关联成员的替代方法。 我们更喜欢在我们的应用程序中使用的标准中将获取模式指定为JOIN

编辑

 Set favourites = user.getFavourites(); 

上面的语句实际上并不返回包含所有Foo对象的集合。 它只是一个代理。 仅当访问集合中的元素时才会获取实际的Foo对象,如favorites.iterator()等。此操作显然发生在getFavorites()方法之外。 但getFavorites()方法上的@Transactional注释表明会话将在此方法结束时关闭。

因此,当在collections夹集上调用方法时,会话已经关闭,因此exception。

要解决此问题,您应该使用Criteria对象来检索用户并将获取类型指定为JOIN以便在返回的User对象中填充Foo对象。

有两种解决方案。

  1. 不要使用延迟加载。

    在XML中设置lazy=false或设置@OneToMany(fetch = FetchType.EAGER)在注释中。

  2. 使用延迟加载。

    在XML中设置lazy=true或在注释中设置@OneToMany(fetch = FetchType.LAZY)

    并在web.xml添加filter

       ...   hibernateFilter  org.springframework.orm.hibernate4.support.OpenSessionInViewFilter   sessionFactoryBeanName mySessionFactory    hibernateFilter /*   ...  

mySessionFactory是在applicationContext.xml中定义的sessionFacory bean名称

是的,应该在跨国上下文中访问该对象,否则它将抛出一个LazyInitializationException