永久転移とN+1問題
6912 ワード
えいきゅうてんい
特定のエンティティの永続状態が変更されると、依存エンティティの永続状態はターゲットエンティティとともに反映されます.
@OneToOne、@OneToMany、@ManyToOne、@ManyToManyなどのツールを使用する場合は、Cascadeという名前のプロパティで、依存エンティティの永続的な状態を反映するタイミングを指定できます.
CascadeTypeへの永続的な移行のタイミング
+)refresh():データベースからインスタンス値を再取得
孤立オブジェクト
親エンティティに関連付けられていない子エンティティを孤児オブジェクトと呼び、親エンティティに関連付けられていない子エンティティをJPAから自動的に削除する孤児オブジェクト削除機能を提供します.(orphanRemoval = true)
参照を削除したエンティティは、他の場所で参照されていない孤立したオブジェクトとみなされ、削除されます.
複数のオブジェクト
CascadeType.REMOVE + orphanRemoval = true
親エンティティを削除する場合、CascadeType.REMOVEと孤立Removal=trueは、同じようにサブエンティティを削除します.ただし、親エンティティから子エンティティを削除すると、CascadeTypeとなります.REMOVEはサブエンティティを保持し、rphanRemoval=trueはサブエンティティを孤児オブジェクトと判断して除去する.
関連関係マッピング
表とオブジェクト
1つのデータベース・テーブルは、1つの外部キーで2つのテーブルで結合できますが、オブジェクトは参照フィールドを持つオブジェクトのみで他のオブジェクトを参照できます.」は、オブジェクトの関連関係が一方向であっても、テーブル内の外部キーは双方向です.
構成
JPAより
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を実行します.
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結合とともに使用すると、問題になる可能性がある.
@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とは、永続性コンテンツの変更をデータベースに同期させる操作です.
Reference
この問題について(永久転移とN+1問題), 我々は、より多くの情報をここで見つけました https://velog.io/@sunho6824/영속성-전이와-N1-문제テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol