2

休止状態のセッションで継続的に問題が発生しているため、休止状態のセッションについて多くの質問があります。

Spring 3.1.1 と Hibernate 4.1.3 を使用しています。

最初に、私が取り組んでいるクラス図を示します。

クラス図

コードクラス:

public class Equipement {

  @ManyToOne(fetch = FetchType.LAZY)
  @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
  public getOffice(){
    return office ;
  }

public class Office {    
  @ManyToOne(fetch = FetchType.LAZY)
  @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
  public getService(){
    return service ;
  }

public class Service {
  @ManyToOne(fetch = FetchType.LAZY)
  @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
  public getDepartement(){
    return departement ;
  }

これが私がすべての機器をロードする方法です。

public class HibernateEquipementDao{

  @SuppressWarnings("unchecked")
  public List<Equipement> getAll() {
      return sessionFactory.getCurrentSession().createQuery("from Equipement").list() ;
  }
}

にすべての機器をロードし、List<Equipement> allEquipementsたとえば、ビューに一部のサービスまたは一部の部門の機器のみを入力したいとします。

 List<Equipement> aListOfEquipements = new ArrayList<Equipement>() ;
 for(Equipement equipement : allEquipements)
   if(equipement.getOffice().getService().getName().equals("name"))
     aListOfEquipements.add(equipement) ;

私はいつでもこれをすることができますか?Currentというセッションは常にアクティブですか? 時々私はその例外を受け取ります。 org.hibernate.LazyInitializationException: プロキシを初期化できませんでした - セッションがありません

私の EquipementDao が使用する現在のセッションはどこですか?

機器部門を取得したいときにセッションを開く方法はありますか?

または、続行する別の方法がありますか?セッションを管理する方法と、すべての機器をロードして問題なく他のエンティティにアクセスする方法は?

4

3 に答える 3

3

この問題を解決する方法は 2 つあります。

1. ビューでセッションを開く:

ビューで休止状態設定のオープン セッションを構成できます。プログラムで休止状態を構成している場合は、次の行を使用できます。

jpaProperties.put(org.hibernate.cfg.Environment.ENABLE_LAZY_LOAD_NO_TRANS, true)

もう 1 つの方法は、次のように web.xml でフィルターを宣言することです。

    <filter>
        <filter-name>OpenEntityManagerInViewFilter</filter-name>
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>OpenEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

このアプローチはすべてのシステムに影響を与え、パフォーマンスに悪影響を及ぼす可能性があります。

2. FETCH JOIN:

クエリで FETCH JOIN を使用して、hibernate に強制的にデータをロードさせることができます。次に例を示します。

from Equipement e FETCH JOIN e.office

このアプローチは実行が難しく (システムの多くの点が影響を受けます)、注意が必要です。

3. クエリが返された後に get メソッドを呼び出します。

DAO では、クエリが返された後に get メソッドを呼び出すことができます。私はこの方法は好きではありませんが、通常は機能します。

お役に立てば幸いです。

于 2012-11-29T19:07:13.347 に答える
3

サービスのレイヤーを追加します。あなたの場合、この名前はそれほど幸運ではないことはわかっていますが、このレイヤーには、ロジックを担当するクラスがあります。

いくつかのプロトタイプ:

public class EquipmentService {

   @Inject
   private HibernateEquipementDao dao;

   @Transactional
   public List<Equipement> doSomethingWithEquipmentWithoutLazyException(Equipment equipment){
      List<Equipement> allEquipments = dao.getAll();

      List<Equipement> aListOfEquipements = new ArrayList<Equipement>() ;
      for(Equipement equipement : allEquipements) {
         if(equipement.getOffice().getService().getName().equals("name")) {
             aListOfEquipements.add(equipement) ;
         }
      }
      return aListOfEquipments;
   }

}

非常に重要なのは注釈です。@Transactionalこれは、セッションがメソッドの最初で開き、最後で閉じることを意味するため、LazyLoadingException をスローする方法はありません。

Transactonal に関する興味深いスレッド: @Transactional アノテーションはどこに属しますか?

于 2012-09-24T12:30:55.290 に答える
0

ほとんどのWebアプリケーションでは、現在のトランザクションをリクエスト全体にまたがらせるのが最も簡単で絶対に適切です。最も簡単なアプローチは、トランザクションを開始し、リクエストの最後にコミット/ロールバックするフィルターを用意することです。Spring / Hibernateでは、これはOpen EntityinViewパターンと呼ばれます。Springは、そのためのorg.springframework.orm.jpa.support.OpenEntityManagerInViewFilterを介したフィルター実装を提供します。

このアプローチを使用する場合、ビュー、つまりJSPは同じトランザクションに参加し、リロードする必要はなく、fetchtypeLAZYリレーションの場合にもエンティティをナビゲートできます。

于 2012-09-24T20:32:55.747 に答える