一尘不染

JSF + Hibernate:集合未与任何会话关联

hibernate

首先,我将Java EE与EntityManager和PrimeFaces一起使用Hibernate。

我有一个EJB模块(业务逻辑和域)和两个WAR模块(Jersey WS和JSF PrimeFaces)。

我决定在JSF WAR模块中初始化延迟集合,以避免延迟初始化异常。我不使用扩展实体管理器。

@ManagedBean(name = "company")
@SessionScoped
public class CompanyBean {

    @EJB
    private CompanyFacade cf;

    ...

    public String showDetails(Long id) {
        company = cf.find(id);
        Hibernate.initialize(company.getCompanyTypes());
        Hibernate.initialize(company.getPrimaryUser());
        Hibernate.initialize(company.getBlocked());
        Hibernate.initialize(company.getAddresses());
        Hibernate.initialize(company.getContacts());
        return "DETAILS";
    }

    ...
}

我得到:

Caused by: org.hibernate.HibernateException: collection is not associated with any session at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:474) at org.hibernate.Hibernate.initialize(Hibernate.java:417) at minepackage.CompanyBean.showDetails(CompanyBean.java:79) ...

我不明白 从数据库中获取初始化之前的一行时,必须有一个会话,不是吗?我以类似的方式在WS模块中初始化属性,并且在那里工作。

知道发生了什么事吗?


阅读 237

收藏
2020-06-20

共1个答案

一尘不染

我认为在EJB完成后会话关闭,因此对象处于 分离 状态。所以Hibernate.initialize()不会再工作了。您在这里有多种选择:

  • 在客户端(在您的JSF bean或servlet过滤器中)打开事务。这样,您通话时会话仍将打开Hibernate.initialize()
  • 修改您的EJB以加载完整的对象和所有必需的集合。您可以使用访Hibernate.initialize()存联接和/或在那里使用。
  • 在EJB中创建更细粒度的API。方法类似CompanyFacade.getAddressesByCompany()

我希望将后两者结合起来。使用访存联接在您的find方法中加载一对一和多对一关系,并添加额外的方法来加载一对多集合(如地址)。由于它减少了数据库查询的次数,因此也将提高后端的性能。

2020-06-20