hibernate
レイジーロードとEagerロード
サーチ…
レイジーロードとEagerロード
データの取得または読み込みは、主に、eagerとlazyの2種類に分類されます。
Hibernateを使用するには、pom.xmlファイルの依存関係セクションに最新バージョンを追加してください:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.1.Final</version>
</dependency>
1. Eager LoadingとLazy Loading
私たちがここで議論すべき最初のことは、怠惰な読み込みと熱心な読み込みが何であるかです:
Eager Loadingは、その場でデータの初期化が行われるデザインパターンです。これは、親がフェッチされた時点でコレクションが完全にフェッチされる(すぐにフェッチされる)ことを意味します。
レイジーローディングは、オブジェクトの初期化を必要な時点まで延期するために使用されるデザインパターンです。これにより、アプリケーションのパフォーマンスに効果的に貢献できます。
2.さまざまな種類の読み込みを使用する
レイジーローディングは、次のXMLパラメータを使用して有効にできます。
lazy="true"
例を掘り下げてみましょう。まず、Userクラスがあります。
public class User implements Serializable {
private Long userId;
private String userName;
private String firstName;
private String lastName;
private Set<OrderDetail> orderDetail = new HashSet<>();
//setters and getters
//equals and hashcode
}
私たちが持っているOrderDetailのセットを見てください。 OrderDetailクラスを見てみましょう:
public class OrderDetail implements Serializable {
private Long orderId;
private Date orderDate;
private String orderDesc;
private User user;
//setters and getters
//equals and hashcode
}
UserLazy.hbm.xml
遅延ロードの設定に関係する重要な部分はUserLazy.hbm.xml
です。
<set name="orderDetail" table="USER_ORDER" inverse="true" lazy="true" fetch="select">
<key>
<column name="USER_ID" not-null="true" />
</key>
<one-to-many class="com.baeldung.hibernate.fetching.model.OrderDetail" />
</set>
これは、遅延読み込みが有効になる方法です。遅延読み込みを無効にするには、単にlazy = "false"
を使用するだけです。これによって順番に読み込みが可能になります。以下は、別のファイルUser.hbm.xmlにeager loadingを設定する例です。
<set name="orderDetail" table="USER_ORDER" inverse="true" lazy="false" fetch="select">
<key>
<column name="USER_ID" not-null="true" />
</key>
<one-to-many class="com.baeldung.hibernate.fetching.model.OrderDetail" />
</set>
範囲
これら2つのデザインで遊んでいない人にとっては、怠け者であり熱望する人の範囲は特定のSessionFactoryの セッション内にあります。 Eagerは即座にすべてをロードします。つまり、フェッチするために何かを呼び出す必要はありません。しかし、遅延フェッチでは通常、マップされたコレクション/オブジェクトを取得するためのアクションが必要です。これはセッションの外で怠惰なフェッチを取得するのが問題になることがあります。たとえば、マップされたPOJOの詳細を示すビューがあります。
@Entity
public class User {
private int userId;
private String username;
@OneToMany
private Set<Page> likedPage;
// getters and setters here
}
@Entity
public class Page{
private int pageId;
private String pageURL;
// getters and setters here
}
public class LazzyTest{
public static void main(String...s){
SessionFactory sessionFactory = new SessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
User user = session.get(User.class, 1);
transaction.commit();
session.close();
// here comes the lazy fetch issue
user.getLikedPage();
}
}
セッションの外でlazyをフェッチしようとすると、 lazyinitializeExceptionが発生します。デフォルトですべてのoneToManyや他の関係は怠惰である(オンデマンドDBへの呼び出し)とセッションを閉じているとき、あなたはデータベースと通信するために何の力を持っていないための戦略をフェッチするためです。そのため、私たちのコードはfavoritePageのコレクションを取得しようとしますが、DBをレンダリングするための関連するセッションがないため例外がスローされます。
これを解決するには、以下を使用します。
- ビュー内のセッションを開く - レンダリングされたビューでもセッションを開いたままにします。
- セッションを閉じる前に
Hibernate.initialize(user.getLikedPage())
- これは、コレクション要素を初期化するようにhibernateに指示します