永久転移とN+1問題

6912 ワード

えいきゅうてんい


特定のエンティティの永続状態が変更されると、依存エンティティの永続状態はターゲットエンティティとともに反映されます.
@OneToOne、@OneToMany、@ManyToOne、@ManyToManyなどのツールを使用する場合は、Cascadeという名前のプロパティで、依存エンティティの永続的な状態を反映するタイミングを指定できます.

CascadeTypeへの永続的な移行のタイミング

  • PERSIST-ターゲットエンティティが新しい状態から管理状態に変更されたときの
  • REMOVE-宛先エンティティが管理状態から削除状態に変更された時点
  • DETACH-宛先エンティティが管理から分離された時点
  • に変更されます.
  • MERGE-ターゲットエンティティが分離状態から管理状態に変化する時点
  • REFRESH-エンティティマネージャがrefresh()メソッドを呼び出す時点
  • ALL-は、全ての状態変化を反映する従属エンティティの永続状態
  • である.
    +)refresh():データベースからインスタンス値を再取得

    孤立オブジェクト


    親エンティティに関連付けられていない子エンティティを孤児オブジェクトと呼び、親エンティティに関連付けられていない子エンティティをJPAから自動的に削除する孤児オブジェクト削除機能を提供します.(orphanRemoval = true)
    参照を削除したエンティティは、他の場所で参照されていない孤立したオブジェクトとみなされ、削除されます.
    複数のオブジェクト
  • が参照されている場合、問題が発生する可能性があります.したがって、@OneToOneおよび@OneToManyでのみ使用できます.
  • 親が取り除かれると、子供は孤児になるので、子供も一緒に取り除かれるのは、ケースでREMOVEを設定したのと同じです.
  • 永続コンテキストをリフレッシュするときにdelete SQLを実行します.
  • CascadeType.REMOVE + orphanRemoval = true


    親エンティティを削除する場合、CascadeType.REMOVEと孤立Removal=trueは、同じようにサブエンティティを削除します.ただし、親エンティティから子エンティティを削除すると、CascadeTypeとなります.REMOVEはサブエンティティを保持し、rphanRemoval=trueはサブエンティティを孤児オブジェクトと判断して除去する.

    関連関係マッピング


    表とオブジェクト


    1つのデータベース・テーブルは、1つの外部キーで2つのテーブルで結合できますが、オブジェクトは参照フィールドを持つオブジェクトのみで他のオブジェクトを参照できます.」は、オブジェクトの関連関係が一方向であっても、テーブル内の外部キーは双方向です.

    構成

  • 方向:一方向、双方向
  • 2 2 2つのオブジェクトの間には、1つのオブジェクトだけが参照フィールドを有し、参照は一方向関係であり、2つのオブジェクトは参照フィールドを有し、参照は双方向関係である.
  • 多重性:多対一、一対多、一対一、多対
  • 関連関係の所有者:双方向設定時に関連関係の所有者を決定します.
  • JPAより

  • @JoinColumn宣言を使用して、name属性にマッピングする外部キー名を指定します.
  • を省略すると、フィールド名で参照されるテーブルのプライマリ・キー列名がデフォルトで使用されます.
  • ManyToMany


    リレーショナル・データベースでは、複数対多のリレーションを2つのテーブルで表すことはできません.0であるため、多対多関係を1対多対一関係に分解する接続テーブルが一般的に使用されます.

    @ManyToMany


    接続テーブルを自動的に処理し、ドメインモデルを簡単に便利にします.
    でも!
    接続テーブルに追加のカラムを追加する必要がある場合がありますので、直接定義したほうがいいです.また,プライマリキーにとって,非識別関係は識別関係よりも簡単で便利である.
    +)識別関係:親のプライマリ・キーを子のプライマリ・キー+識別キーとして使用します.非識別関係:親のプライマリ・キーは外部キーとしてのみ使用され、新しいプライマリ・キーが定義されます.

    OneToMany


    1対のマルチ一方向マッピングの欠点は、マッピングオブジェクト管理の外部キーが別のテーブルにあることです.
    ->テーブルに外部キーがある場合は、クエリーを一度に挿入してエンティティの格納と関連マッピング処理を完了できますが、別のテーブルにあるため、関連関係マッピング処理のための更新クエリー(外部キーを持つエンティティ)を実行する必要があります.
    したがって、1対のマルチ一方向マッピングでは、パフォーマンスの問題と管理コストが発生するため、マルチ対1の双方向マッピングが有効です.

    OneToOne


    1対1の関係は、プライマリ・テーブルまたはターゲット・テーブルのいずれかであり、選択する必要があります.必要に応じて双方向
    一般的にメインテーブルには外来キーがある方が便利なので人気があります.

    双方向


    双方向は実際には2つの一方向関係であり、mappedByプロパティを使用して、外部キーをはじめとする制御権限を持つ関連関係の所有者を指定する必要があります.すなわち、mappedByプロパティは、関連関係の所有者であるエンティティの参照フィールド(外部キー)を指定する必要があります.
    +)関連付けられた関係の所有者は、関連付けられた関係を持つ2つのオブジェクト間でクエリー、保存、変更、削除を行うことができますが、関連付けられた関係の所有者でない場合はクエリーのみを実行できます.
    +)データベースは無条件に(N)側が外部キーを持つ.
    デフォルトでは、一方向マッピングを追加し、後でオブジェクトをリバースブラウズする必要があると感じたら追加することが望ましい.

    むげんループ


    JPAの双方向マッピング関係では,うまくいかなければ無限ループが生じる可能性がある.
    この場合、通常、シンボルをJSONに変換する場合に発生する.たとえば、メンバー、チームが双方向関係にある場合、メンバーエンティティがJSONに変換されると、メンバーはチームがJSONに変換する過程で無限ループを生成します.
    したがって、通常はdtoを作成し、JSONに変換するデータのみを定義し、そのdtoでJSONを作成します.

    JPQL


    Java Persistence Query Languageの略で、データベース・テーブルではなくエンティティ・オブジェクトに対するオブジェクト・クエリーです.JPAは、JPA Repositoryのインタフェースメソッド名を継承してJPQLに変換する分析を行い、SQLを作成してDBでSQLを実行します.
  • jpql抽象SQL、特定のデータベースに依存しません.
  • データベースサマリーを変更するだけで、jpqlを変更せずに(標準関数を使用して)データベースを変更できます.
  • N+1問題


    jpaのentityクエリはQueryを生成し,内部に存在する他の関連関係にアクセスするとクエリはデータ個数Nに等しいクエリを生成する.

    オカレンスケース


    インスタントロード


    理論的には、即時ローディングは一度SQLを結合してテーブル情報を問合せますが、JPQLを実行すると問題が発生します.
    たとえば、メンバー情報を問い合わせると、メンバーエンティティクエリーライブラリ(1)が実行され、そのメンバーの受注データを参照するN個のSQLが、関連する受注エンティティ上で実行されます.

    ディレイロード


    最初は、エンティティのみをクエリーするクエリーが1回実行されますが、オブジェクトの初期化時に初期化された数はN+1の問題を引き起こします.

    解決策


    パッチ結合


    これはJPQLで最もよく使われる性能最適化方法である.
    select distinct m from Member m join fetch m.orders
    パッチ結合は内部結合であるため、一対の多関係で一対のテーブルクエリデータに基づいているとカウント乗算が発生し、重複データが発生するため、distinctを同時に使用する必要があります.

    fetch結合制限


  • ページング問題
    JPAはPageableインタフェースで簡単なページ処理機能を提供しています.ただし、N+1の問題を回避するために使用するfetch結合とともに使用すると、問題になる可能性がある.
  • ToOneプレゼンテーションによって確立された関係であれば、データ量はテーブル結合によって変化しないため、ページング処理を行うことができる.
  • ToManyプレゼンテーションで作成された関係の場合、テーブル結合によってデータが変更されるため、ページング処理とページング結合を同時に行うことはできません.この場合、ページングとページング結合を同時に使用すると、dbからデータインポートを切り取るのではなく、データをすべてメモリに格納し、アプリケーション側でページングを実行する警告ログが残ります.
  • @EntityGraphを使用したプレゼンテーション


    @EntityGraphアニメーションに結合するエンティティフィールドを指定します.クエリーは別途作成する必要がないので便利です.
    	@EntityGraph(attributePaths = {"team"}) 
        List<Member> findAll();

    超ワイド@BaschSize


    関連するエンティティをクエリーする場合は、SQLのinセクションを使用して指定したsizeに従ってクエリーを行います.たとえば、sizeが5で、合計データが10の場合、SQLは2回実行されます.
          @BatchSize(size = 5)  
          @OneToMany(mappedBy = "member", fetch = FetchType.EAGER) 
          private List<Order> orders = new ArrayList<Order>();

    JPAその他の問題


    @Transaction(read=true)をクエリー操作で使用する場合、パフォーマンスが向上するのはなぜですか?


    read=true属性がオンの場合、JPAは永続性コンテキストをリフレッシュしません.Flushとは、永続性コンテンツの変更をデータベースに同期させる操作です.