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数据库操作。
这几乎适用于我的Oracle11DB中的所有enities,但有些(似乎是随机的)失败了,原因是"org.hibernate.HHibernate异常:collection与任何会话都不关联"。据我所知,之所以会发生这种情况,是因为PersistentSet中的会话已关闭,但为什么它一开始就关闭了?
最奇怪的是,如果我在这一行上放置一个断点,并在调试器中调用Hibernate.initialize()(即在eclipse Inspect窗口中),它就会成功加载集合。
什么可以关闭会话?有什么好的开始调试的地方吗(比如Hibernate中的某个断点)
更新:
我在职位类中有另一种关系:
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "POSITION_NUMBER", referencedColumnName = "POSITION_NUMBER", insertable = false, updatable = false)
public Set<Child> getChildren() {
return children;
}
对于失败的行,它是空的,但将其更改为@Transient会使问题消失。
您可能需要使用处理会话打开和关闭的OpenSessionInViewFilter。您没有指定Spring/HHibernate版本,因此可能需要进行调整。
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>
我的问题中显然没有足够的数据来找到正确的答案。抱歉。
因此,与社区分享我的经验:问题是第二个密钥(POSITION_NUMBER)在第一个集合中不是唯一的,所以hibernate加载了这个集合两次,第二次初始化失败。不知道是什么让它在调试器中正常运行,但修复数据解决了问题。
所以我真正缺少的是键列上的唯一约束。