有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

显式EntityManager之后@RequestScoped Bean中的java LazyInitializationException。发现

我们目前正在从JavaEE5迁移到JavaEE6,并使用JBoss6.0.0和JSF2。为了简单起见,这个示例是基于Maven原型构建的:org.jboss.weld.archetypes:jboss-javaee6-webapp:1.0.1.CR2

我在User中添加了一个简单的惰性关系:

@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,并从相同的EntityManager em显式加载Member m2。现在有趣的部分: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

谁能解释一下,或者知道如何解决这个问题?谢谢你,托尔


共 (3) 个答案

  1. # 1 楼答案

    这是惰性加载的正常行为,所有惰性类都是代理类。当您从代理获取类时,您的Hibernate会话已经关闭

    解决方案是实现视图中的Open Session Filter,它将保持您的Hibernate会话处于打开状态,直到您的请求处于活动状态

    你可以在这篇文章中了解更多

    http://community.jboss.org/wiki/OpenSessionInView

    如果您使用的是Spring框架,那么您已经在OpenSessionInViewFilter类中完成了这项工作

    希望能有帮助

  2. # 2 楼答案

    您可以通过下面给出的代码动态获取相关对象,该代码具有默认的延迟初始化:

    标准。setFetchMode(“地址”,FetchMode.JOIN)

  3. # 3 楼答案

    托尔,你能再检查一下吗?我觉得这很有趣,自己也试过了,但我在两次通话中都遇到了例外。他们两个都不工作。我可能做错了什么,但我已经检查了几次,两种方法都给了我这个例外。您是否让记录器记录第一次收集的大小