Hibernate load()メソッドのプロキシ

1。概要

このチュートリアルでは、Hibernateのload()メソッドのコンテキストでプロキシが何であるかを確認します。

Hibernateを初めて使用する読者は、最初に基本を理解することを検討してください。

2.プロキシとload()メソッドの簡単な紹介

定義上、プロキシは「代理人または別の代理人として機能することを許可された機能」です。

これは、Session.load()を呼び出して、目的のエンティティクラスの初期化されていないプロキシと呼ばれるものを作成するときにHibernateに適用されます

簡単に言うと、HibernateはCGLibライブラリを使用してエンティティクラスをサブクラス化します。@Idメソッドを除いて、プロキシ実装は他のすべてのプロパティメソッドをHibernateセッションに委任して、インスタンスにデータを入力します。

public class HibernateProxy extends MyEntity {     private MyEntity target;     public String getFirstName() {         if (target == null) {             target = readFromDatabase();         }         return target.getFirstName();     } }

このサブクラスは、データベースに直接クエリを実行する代わりに返されるサブクラスになります。

エンティティメソッドの1つが呼び出されると、エンティティがロードされ、その時点で初期化されたプロキシになります。

3.プロキシと遅延読み込み

3.1。単一のエンティティ

従業員をエンティティとして考えてみましょう。まず、他のテーブルとは関係がないと仮定します。

Session.load()を使用して従業員をインスタンス化する場合:

Employee albert = session.load(Employee.class, new Long(1));

次に、HibernateはEmployeeの初期化されていないプロキシを作成します。指定したIDが含まれますが、データベースにまだアクセスしていないため、それ以外の値はありません。

ただし、albertでメソッドを呼び出すと:

String firstName = albert.getFirstName();

次に、Hibernateは従業員データベーステーブルに主キーが1のエンティティを照会し、対応する行からアルバートにプロパティを入力します。

行が見つからない場合、HibernateはObjectNotFoundExceptionをスローします

3.2。1対多の関係

それでは、会社に多くの従業員がいる会社エンティティも作成しましょう

public class Company {     private String name;     private Set employees; }

今回は会社でSession.load()を使用する場合:

Company bizco = session.load(Company.class, new Long(1)); String name = bizco.getName();

次に、従業員のセットが少し異なることを除いて、会社のプロパティが以前と同じように入力されます。

参照してください。会社の行のみを照会しましたが、フェッチ戦略に応じてgetEmployeesを呼び出すまで、プロキシは従業員をそのままにしておきます。

3.3。多対1の関係

ケースは反対方向でも同様です。

public class Employee {     private String firstName;     private Company workplace; }

load()を再度使用する場合:

Employee bob = session.load(Employee.class, new Long(2)); String firstName = bob.getFirstName();

これでb​​obが初期化され、実際には、フェッチ戦略に応じて、workplaceが初期化されていないプロキシに設定されます。

4.怠惰な読み込み

現在、load()は常に初期化されていないプロキシを提供するとは限りません。実際、Session java docは私たちに思い出させます(強調が追加されました):

このメソッド、識別子以外のメソッドにアクセスすると、オンデマンドで初期化されるプロキシインスタンスを返す場合があります。

これが発生する可能性のある簡単な例は、バッチサイズです。

Employeeエンティティで@BatchSizeを使用しているとしましょう。

@Entity @BatchSize(size=5) class Employee { // ... }

今回は3人の従業員がいます。

Employee catherine = session.load(Employee.class, new Long(3)); Employee darrell = session.load(Employee.class, new Long(4)); Employee emma = session.load(Employee.class, new Long(5));

私たちは、呼び出した場合getFirstNameをキャサリン

String cathy = catherine.getFirstName();

次に、実際には、Hibernateは3人の従業員すべてを一度にロードして、3人すべてを初期化されたプロキシに変えることを決定する場合があります。

そして、ダレルの名を呼ぶとき:

String darrell = darrell.getFirstName();

その場合、Hibernateはデータベースにまったくヒットしません。

5.積極的な読み込み

5.1。get()の使用

プロキシを完全にバイパスし、Session.get()を使用してHibernateに本物をロードするように依頼することもできます

Employee finnigan = session.get(Employee.class, new Long(6));

これにより、プロキシを返す代わりに、データベースがすぐに呼び出されます。

そして実際に、代わりにObjectNotFoundException、それが返されますヌルを場合フィニガンは存在しません。

5.2。パフォーマンスへの影響

一方でGET()が便利です、負荷()は、データベース上の軽量化することができます。

たとえば、ジェラルドが新しい会社で働くとしましょう。

Employee gerald = session.get(Employee.class, new Long(7)); Company worldco = (Company) session.load(Company.class, new Long(2)); employee.setCompany(worldco); session.save(employee);

この状況のみ従業員レコードを変更することがわかっているので、Companyに対してload()を呼び出すのが賢明です。

私たちが呼び出された場合()を取得する上で、当社は、我々は、データベースから不すべてのデータをロードしていると思います。

6.結論

この記事では、Hibernateプロキシがどのように機能し、これがエンティティとその関係のロードメソッドにどのように影響するかを簡単に学びました。

また、load()get()の違いについても簡単に説明しました

いつものように、チュートリアルに付属する完全なソースコードは、GitHubから入手できます。