セッションのキャッシュは、相互に関連するオブジェクトグラフで保存されます。デフォルトでは、Hibernateがデータベースから顧客オブジェクトをロードすると、すべての関連する注文オブジェクトが同時にロードされます。顧客と注文のクラスを例として取得するには、注文テーブルの顧客_ID外部キーがnullになることを許可されていると仮定します
次のSession的find()メソッドは、データベース内のすべての顧客オブジェクトを取得するために使用されます。
List customerLists=session.find("from Customer as c");
上記のfind()メソッドを実行すると、Hibernateは最初に顧客テーブルのすべてのレコードを照会し、次に各レコードのIDに基づいて参照関係で注文テーブルを照会します。 Hibernateは、次の選択ステートメントを順番に実行します。
select * from Customers;
customer_id = 1;
customer_id = 2;
customer_id = 3;
customer_id = 4;
上記の5つの選択ステートメントを通して、Hibernateは最終的に4つの顧客オブジェクトと5つの注文オブジェクトをロードし、メモリに関連するオブジェクトグラフを形成します。
Hibernateは、顧客に関連付けられた注文オブジェクトを取得するときに、デフォルト検索Nowポリシーを使用します。この検索戦略には2つの主要な欠点があります。
(1)選択されたステートメントの数が大きすぎてデータベースに頻繁にアクセスできるようになり、検索パフォーマンスに影響します。 nカスタマーオブジェクトを照会する必要がある場合は、n+1の選択クエリステートメントを実行する必要があります。これは、古典的なn+1の選択クエリの問題です。この検索戦略は、SQLの接続クエリ関数を使用しません。たとえば、上記の5つの選択ステートメントは、次の1つの選択ステートメントによって完全に完了できます。
customerから左の外側の結合注文から *を選択します
customers.id = orders.customer_id
上記のSelectステートメントでは、SQLの左外結合クエリ関数を使用します。これにより、顧客テーブルのすべてのレコードと一致する注文テーブルの記録が選択されています。
(2)アプリケーションロジックが顧客オブジェクトにのみアクセスする必要があるが、オブジェクトを注文する必要がある状況では、注文オブジェクトのロードは完全に不要です。これらの不要な注文オブジェクトは、多くのメモリスペースを無駄にします。
上記の問題を解決するために、Hibernateは他の2つの検索戦略を提供します。遅延検索戦略と緊急の左翼接続検索戦略です。遅延検索戦略は、アプリケーションがアクセスする必要のない関連オブジェクトの冗長な負荷を回避できます。緊急の左外の接続検索戦略により、SQLの外側接続クエリ関数を最大限に活用し、選択されたステートメントの数を減らすことができます。
データベースにアクセスするときは、パフォーマンスの問題を考慮する必要があります。 1対多数の関係を設定した後、クエリで伝説的なN +1問題が発生します。
1)1に1つの正方形に、Nオブジェクトが見つかり、Nオブジェクトに関連付けられたセットを取り出す必要があるため、元のSQLクエリはn +1になります
2)1〜1。複数のパーティでMオブジェクトを照会すると、Mオブジェクトに対応する1パーティオブジェクトが取り出され、M+1にもなります。
1)lazy = true、hibernate3は既にdefored = trueにデフォルトである。 lazy = trueの場合、関連するオブジェクトはすぐに照会されません。クエリアクションは、関連するオブジェクト(その属性、非IDフィールドにアクセス)の場合にのみ発生します。
2)レベル2キャッシュ。オブジェクトの更新、削除、および追加されたクエリよりもはるかに少ない場合、レベル2キャッシュの適用はn +1の問題を恐れません。これは、最初のクエリが遅い場合でも、キャッシュヒットはその後非常に高速になるためです。
さまざまなソリューションとさまざまなアイデアがありますが、2番目のソリューションはたまたまn +1を再び使用します。
3)もちろん、 fetch=join(annotation : @ManyToOne() @Fetch(FetchMode.JOIN))を設定することもできます。
上記は、Hibernate N+1の問題に関するこの記事の簡単な議論に関するものであり、誰にとっても役立つことを願っています。興味のある友人は、このサイトの他の関連トピックを引き続き参照できます。欠点がある場合は、それを指摘するためにメッセージを残してください。このサイトへのご支援をありがとうございました!