2

首先,我使用 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 模块中的属性并且它在那里工作。

知道发生了什么吗?

4

1 回答 1

6

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

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

我更喜欢后两者的组合。使用 fetch 连接在您的方法中加载一对一和多对一关系,find并添加额外的方法来加载一对多集合(如地址)。这也将提高后端的性能,因为它减少了数据库查询的数量。

于 2012-06-07T08:41:22.170 回答