私は Java Persistence API と Hibernate の初心者です。
Java Persistence APIのFetchType.LAZY
との違いは何ですか?FetchType.EAGER
私は Java Persistence API と Hibernate の初心者です。
Java Persistence APIのFetchType.LAZY
との違いは何ですか?FetchType.EAGER
2 つのエンティティがあり、それらの間に関係がある場合があります。たとえば、エンティティと呼ばれるUniversity
別のエンティティがStudent
あり、大学には多くの学生がいるとします。
University エンティティには、id、名前、住所などのいくつかの基本的なプロパティと、特定の大学の学生のリストを返す学生と呼ばれるコレクション プロパティがあります。
public class University {
private String id;
private String name;
private String address;
private List<Student> students;
// setters and getters
}
これで、データベースから大学をロードすると、JPA が ID、名前、およびアドレス フィールドをロードします。ただし、学生の読み込み方法には 2 つのオプションがあります。
getStudents()
大学のメソッドを呼び出すときに、オンデマンドで (つまり遅延して) ロードします。大学に多くの学生がいる場合、すべての学生を一緒にロードするのは効率的ではありません。特に、学生が必要でない場合はそうです。このような場合、学生が実際に必要なときに学生をロードするように宣言できます。これは遅延読み込みと呼ばれます。
これは例です。ここでstudents
は、熱心に読み込まれるように明示的にマークされています。
@Entity
public class University {
@Id
private String id;
private String name;
private String address;
@OneToMany(fetch = FetchType.EAGER)
private List<Student> students;
// etc.
}
students
そして、遅延ロードするように明示的にマークされている例を次に示します。
@Entity
public class University {
@Id
private String id;
private String name;
private String address;
@OneToMany(fetch = FetchType.LAZY)
private List<Student> students;
// etc.
}
基本的、
LAZY = fetch when needed
EAGER = fetch immediately
EAGER
コレクションのロードとは、親がフェッチされた時点でコレクションが完全にフェッチされることを意味します。したがって、 がありCourse
、 が ある場合、 が取得された時点List<Student>
ですべての学生がデータベースからCourse
取得されます。
LAZY
一方、の内容は、List
アクセスしようとしたときにのみ取得されることを意味します。たとえば、 を呼び出しcourse.getStudents().iterator()
ます。で任意のアクセス メソッドをList
呼び出すと、データベースへの呼び出しが開始され、要素が取得されます。List
これは、 (または)の周りにプロキシを作成することによって実装されSet
ます。したがって、遅延コレクションの場合、具象型はArrayList
andHashSet
ではなくPersistentSet
and PersistentList
(or PersistentBag
)です。
パフォーマンスとメモリ使用率を考慮する場合があります。大きな違いの 1 つは、EAGER フェッチ戦略では、フェッチされたデータ オブジェクトをセッションなしで使用できることです。なんで?
セッションが接続されたときにオブジェクト内のデータを熱心にマークすると、すべてのデータがフェッチされます。ただし、遅延読み込み戦略の場合、セッションが切断されている場合 (session.close()
ステートメントの後)、マークされたオブジェクトの遅延読み込みはデータを取得しません。休止状態のプロキシによって作成できるすべて。Eager 戦略により、セッションを閉じた後もデータを引き続き利用できます。
と の両方FetchType.LAZY
をFetchType.EAGER
使用して、デフォルトのフェッチ プランを定義します。
残念ながら、LAZY fetching のデフォルトのフェッチ プランのみをオーバーライドできます。EAGER フェッチは柔軟性が低く、多くのパフォーマンスの問題を引き起こす可能性があります。
私のアドバイスは、フェッチはクエリ時の責任であるため、アソシエーションを EAGER にする衝動を抑えることです。そのため、すべてのクエリでfetchディレクティブを使用して、現在のビジネス ケースに必要なものだけを取得する必要があります。
Javadocから:
EAGER 戦略は、永続化プロバイダーのランタイムで、データを熱心にフェッチする必要があるという要件です。LAZY 戦略は、データが最初にアクセスされたときにデータを遅延して取得する必要があるという持続性プロバイダーのランタイムへのヒントです。
たとえば、熱心は怠惰より積極的です。Lazy は最初の使用時にのみ発生しますが (プロバイダーがヒントを取得した場合)、Eager の場合は (可能性があります) プリフェッチされます。
public enum FetchType extends java.lang.Enum データベースからデータを取得するための戦略を定義します。EAGER 戦略は、永続化プロバイダーのランタイムで、データを熱心にフェッチする必要があるという要件です。LAZY 戦略は、データが最初にアクセスされたときにデータを遅延して取得する必要があるという持続性プロバイダーのランタイムへのヒントです。実装は、LAZY 戦略ヒントが指定されているデータを積極的にフェッチすることが許可されています。例: @Basic(fetch=LAZY) protected String getName() { return name; }
@drop-shadow Hibernate を使用している場合は、メソッドHibernate.initialize()
を呼び出すときに呼び出すことができます。getStudents()
Public class UniversityDaoImpl extends GenericDaoHibernate<University, Integer> implements UniversityDao {
//...
@Override
public University get(final Integer id) {
Query query = getQuery("from University u where idUniversity=:id").setParameter("id", id).setMaxResults(1).setFetchSize(1);
University university = (University) query.uniqueResult();
***Hibernate.initialize(university.getStudents());***
return university;
}
//...
}