A有两个hibernate实体和一个简单的1:N集合关系:
@Entity
public class Root {
@OneToMany(mappedBy = "root", fetch = FetchType.LAZY)
public Set<Position> getPositions() {
return positions;
}
}
并且Spring MVC Web应用程序加载根实体并初始化延迟集合:
@Transactional
public Root findFullById(Long id) {
Root root = (Root) getSession().get(Root.class, id);
Hibernate.initialize(root.getPositions()); // this line fails
return root;
}
此方法之前有 NO 数据库操作。
这适用于我的Oracle 11 DB中的几乎所有实体,但有些(似乎是随机的)使用&#34; org.hibernate.HibernateException失败:集合与任何会话都没有关联#34;。据我所知,这是因为PersistentSet中的会话已关闭,但为什么它首先关闭?
最奇怪的是,如果我在这一行放置一个断点并在调试器中调用Hibernate.initialize()(即在eclipse Inspect窗口中),它会成功加载该集合。
什么可以关闭会话?是否有任何好的调试地点(即Hibernate中的断点)?
更新
我在Position课程中有另一种关系:
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "POSITION_NUMBER", referencedColumnName = "POSITION_NUMBER", insertable = false, updatable = false)
public Set<Child> getChildren() {
return children;
}
对于失败的行,它是空的,但将其更改为@Transient会使问题消失。
答案 0 :(得分:0)
您可能需要使用OpenSessionInViewFilter来处理会话打开和关闭。您没有指定Spring / Hibernate版本,因此可能需要进行调整。
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>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>
</filter>
答案 1 :(得分:0)
在我的问题中定义的数据不足以找到正确的答案。对不起。
所以与社区分享我的经验:问题是第二个密钥(POSITION_NUMBER)在第一个集合中不是唯一的,所以hibernate加载了这个集合两次,第二次初始化失败。不知道在调试器中是什么使得它没问题,但是修复数据解决了这个问题。
所以我真正缺少的是关键列的唯一约束。