[JPA]13章Webアプリケーションと持続性管理


この記事は、キム・ヨンハンの『Java ORM標準JPAプログラミング』を読んで学習内容を整理したものだ.
コンテナ環境でのJPA動作の内部動作を知る.
コンテナ環境でWebアプリケーションを開発する際に発生する可能性のあるさまざまな問題と解決策を検討します.

1.取引範囲の永続性コンテキスト


1.1スプリング容器の基本戦略



  • スプリングは、トランザクション範囲の永続性コンテキストを基本ポリシーとして使用します.

  • トランザクション範囲は、永続性コンテキストの生存範囲と同じであり、トランザクションが終了すると、永続性コンテキストも終了します.

  • Springアプリケーションでは@Transactionalを使用してトランザクションを開始しますが、単純呼び出しのように見える部分は実際にSpringのトランザクションAOPが最初に動作します.

  • トランザクションが同じ場合は、同じ永続性コンテキストが使用されます.
    エンティティマネージャ(Entity Manager)を別の場所で使用しても、トランザクションが同じ場合は常に同じ永続性コンテキストを使用します.

  • トランザクションが異なる場合は、異なる永続性コンテキストが使用されます.
    複数のスレッドから同時に要求された場合、同じエンティティマネージャを使用しても、トランザクションによってアクセスの持続性コンテキストが異なります.
  • 1.2準永久状態と遅延負荷


  • クエリーのエンティティはトランザクション範囲のサービスであり、リポジトリ・レイヤでは永続性コンテキストによって管理されるため、永続性は維持されますが、他のレイヤでは準永続性になります.

  • 永続性コンテキストの管理に加えて、遅延ロードと変更検出は機能しません.
  • に必要な要素を予めロードすることにより、遅延ロードを使用することができる.
  • グローバルパッチ戦略改訂
  • JPQLプレ締結
  • 強制初期化
  • FACADE層
  • OSIVを使用して、エンティティを常に永続的な状態にする
  • .

    グローバルバッチ・ポリシーの変更

    @Entity
    public class Order {
        @Id @GeneratedValue
        private Long id;
        
        @ManyToOne(fetch=FetchType.EAGER)	// 즉시 로딩
        private Member member;
    }

  • 未使用のエンティティをロードします.

  • N+1の問題が発生しました.
  • JPQLバッチ結合


  • JPQLバッチ結合では、呼び出し時に一緒にロードするエンティティを選択できます.

  • JPQLプリフェッチ結合を使用するように変更した場合は、SQL JOINを使用してプリフェッチ結合オブジェクトをクエリーします.したがってN+1の問題は発生しない.

  • 最も現実的な代替案

  • 盲目的に使用すると、画面に一致するrepositoryメソッドが増加します.
  • 画面Aのオーダーのみを問い合わせるリポジトリです.findOrder()メソッド
  • 画面Bに対して、orderに関連付けられたメンバーをプリフェッチ結合されたリポジトリとしてクエリーします.findOrderWithMember()メソッド
    ->ビューとリポジトリの間に論理依存関係があります.
  • 強制初期化

    class OrderService{
        @Transactional
        public Order findOrder(id){
            Order order = orderRepository.findOrder(id);
            order.getMember().getName();	// 프록시 객체를 강제로 초기화한다.
            return order;
        }
    }

  • トランザクション内で初期化を強制して戻し、準永続状態でも使用できるようにします.

  • 必要に応じて表示するエンティティによってサービス・レイヤの論理を変更する必要があるため、プレゼンテーション・レイヤがサービス・レイヤを侵害する可能性があります.
  • FACADEレイヤー



  • プレゼンテーションレイヤで必要なプロキシオブジェクトを初期化します.

  • 中間に階層が1つ増えているので、より多くのコードを書く必要があります.
  • すべての問題は、エンティティがプレゼンテーションレイヤで準永続状態にあるためです.

    2. OSIV


    -> Open Session In View
    永続性コンテキストをプレゼンテーションレイヤに開きます.

    2.1過去OSIV:オンデマンド取引



  • テンプレートフィルタまたはスプリングコネクタから永続性コンテキストを作成するには

  • トランザクションが開始され、リクエストの終了時にトランザクションと永続性コンテキストが同時に終了します.

  • 遅延ロードを処理するためにプロキシオブジェクトを初期化する必要はありません.

  • データの変更は、非ビジネス・レベルで発生する可能性があります.
    ->プレゼンテーションレイヤでのエンティティの変更を防止する方法
  • エンティティは、読み取り専用インタフェースとして
  • を提供する.
  • エンティティ展開
  • DTOのみが
  • を返す.

    2.2春季OSIV:業務層事務



  • クライアントがリクエストを発行すると、フラットパネルフィルタまたはインタフェースに永続性コンテキストが作成されます.(取引X)

  • サービス・レベルでトランザクションが開始されると、前に作成した永続性コンテキストでトランザクションが開始されます.

  • サービス・レイヤが終了すると、トランザクションがコミットされ、永続性コンテキストがリフレッシュされます.トランザクションのみを終了します.(永続コンテキストX)

  • リクエストの終了時に永続性コンテキストを終了します.
  • トランザクション読み込みなし


    ->変更はトランザクション内で行う必要があります.クエリー時にトランザクションは必要ありません.
    初期化エージェントオブジェクトの遅延ロードもクエリーなので、トランザクションを必要とせずに読み込むことができます.

    注意点


    コントローラでエンティティ値を変更し、すぐにビューにデータを返さずに別のサービスメソッドを呼び出してトランザクションを開始すると、問題が発生します.
    コントローラで変更した値は、トランザクションコミットによって実際のデータベースに反映されるためです.
    ->取引を含むすべてのビジネスロジックを呼び出し、エンティティを変更します.

    OSIVを使う方法は万能ではない。


  • OSIVを使用すると、画面を出力するときにエンティティを保持し、オブジェクトグラフィックで任意に参照できます.

  • 複雑な画面を構築する場合、この方法は無効になることが多い.
  • の複雑な統計画面は、エンティティで検索するよりも、統計データを構想するためのJPQLを最初から作成し、DTOで検索する方が効果的です.