failed to lazily initialize a collection of role、could not initialize proxy – no Sessionへの対応

Pocket

Spring Boot(Hibernate)で表題のエラーが出た場合の対処です。

この辺を参考にしました。
Hibernate could not initialize proxy – no Session

このエラーは、例えば以下のようにユーザーBean内で所属クラスBeanを持たせるような関連を作っている場合に発生します。

public class UserBean {
    (略)
    @OneToMany(orphanRemoval = true, cascade = CascadeType.ALL)
    private Set<UserClassBean> userClassBeans;
    (略)
}

上記、所属クラスBeanのSetに対するフェッチがデフォルトでFetchType.LAZYになるので、遅延フェッチされます。

所属クラスがあるはずなのに取得ができず、またデータレイヤでsessionが終了しているために改めてDBから取得することもできない状態になります。

単純にFetchType.EAGERを指定しておけば遅延フェッチは発生しなくなりますが、負荷が大きいため推奨されていない様子です。
ビューレイヤでSessionを開く方法などもあるようですが、こちらも推奨されていない様子。

どうやらJPQLでJOIN FETCHを行うメソッドを定義するのがよいとのこと。

というわけでUserBeanを取得する際に、Set<UserClassBean>をJOIN FETCHするメソッドをUserBean用のRepositoryに実装しました。
findByIdのJOIN FETCH版です。

public class UserRepository extends JpaRepository... {
    (略)
    @Query("SELECT DISTINCT u FROM UserBean u LEFT JOIN FETCH u.userClassBeans WHERE u.id = :id")
    Optional<UserBean> findByIdFetchUserClass(@Param("id") String id);
    (略)
}

ちなみにJOIN FETCHでなく、LEFT JOIN FETCHとしておかないと、SET<UserClassBean>を持たない(クラスに所属しない)ユーザーが取得できませんでした。

広告

Pocket

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です