我们目前正在从JavaEE5迁移到JavaEE6,并且正在使用JBoss 6.0.0和JSF2。为简单起见,此示例是基于Maven原型构建的:org.jboss.weld.archetypes:jboss-javaee6-webapp:1.0.1.CR2
我在User
添加了一个简单的LAZY关系:
@NotNull @ManyToMany(fetch=FetchType.LAZY)
private List<Address> addresses;
这个bean是maven原型的一部分,我向retrieveAllMembersOrderedByName()
添加了几行。
@RequestScoped
public class MemberListProducer {
@Inject private Logger log;
@Inject @MemberRepository
private EntityManager em;
private List<Member> members;
@Produces @Named
public List<Member> getMembers(){return members;}
@PostConstruct
public void retrieveAllMembersOrderedByName()
{
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> criteria = cb.createQuery(Member.class);
Root<Member> member = criteria.from(Member.class);
criteria.select(member).orderBy(cb.asc(member.get("name")));
members = em.createQuery(criteria).getResultList();
Member m1 = members.get(0);
log.info("Id: "+m1.getId());
Member m2 = em.find(Member.class, m1.getId());
log.info("Addr m1: "+m1.getAddresses().size()); // OK
log.info("Addr m2: "+m2.getAddresses().size()); // Error
}}
如您所见,CriteriaQuery检索到List<Member>
,然后从列表中取出Member m1
,并从同一Member m2
显式加载EntityManager em
。现在有趣的部分:m1.getAddresses().size()
有效,m2.getAddresses().size()
给出了
15:41:32,910 ERROR [org.hibernate.LazyInitializationException]
failed to lazily initialize a collection of role: test.Member.addresses,
no session or session was closed: org.hibernate.LazyInitializationException:
failed to lazily initialize a collection of role:test.Member.addresses,
no session or session was closed
任何人都可以解释一下,或者知道如何解决这个问题?谢谢,托尔
答案 0 :(得分:0)
这是延迟加载的所有惰性类都是代理的正常行为。当你从代理中提取类时,你的Hibernate会话已经关闭。
解决方案是在View Filter中实现Open Session,这将使您的Hibernate会话保持打开状态,直到您的Request处于活动状态。
您可以在本文中阅读更多相关信息
http://community.jboss.org/wiki/OpenSessionInView
如果您使用的是Spring Framework,那么您已经完成了OpenSessionInViewFilter
课程。
希望它有所帮助。
答案 1 :(得分:0)
答案 2 :(得分:0)
您可以通过下面给出的具有默认延迟初始化的代码动态获取相关对象:
criteria.setFetchMode(“addresses”,FetchMode.JOIN);