2

まず、Java EE、EntityManagerおよびPrimeFacesでのHibernateを使用します。

1つのEJBモジュール(ビジネスロジックとドメイン)と2つのWARモジュール(JerseyWSとJSFPrimeFaces)があります。

遅延初期化の例外を回避するために、JSFWARモジュールで遅延コレクションを初期化することにしました。拡張エンティティマネージャーは使用しません。

@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) ...

わかりません。初期化の1行前にデータベースからフェッチされたときにセッションが必要ですよね。同様の方法でWSモジュールの属性を初期化し、そこで機能しています。

何が起こっているのか分かりますか?

4

1 に答える 1

6

EJBが終了するとセッションが閉じられるため、オブジェクトは切り離された状態になっていると思います。だからHibernate.initialize()もう動作しません。ここには複数のオプションがあります。

  • クライアント側でトランザクションを開きます(JSF Beanまたはサーブレットフィルターで)。このようにすると、呼び出しているときにセッションが開いたままになりますHibernate.initialize()
  • EJBを変更して、オブジェクト全体と必要なすべてのコレクションをロードします。フェッチ結合を使用したり、Hibernate.initialize()そこで使用したりできます。
  • EJBでよりきめ細かいAPIを作成します。のような方法CompanyFacade.getAddressesByCompany()

私は後者の2つの組み合わせを好みます。フェッチ結合を使用して、メソッドに1対1および多対1の関係findをロードし、1対多のコレクション(アドレスなど)をロードするためのメソッドを追加します。これにより、データベースクエリの数が減るため、バックエンドのパフォーマンスも向上します。

于 2012-06-07T08:41:22.170 に答える