2017-10-18 8 views
1

多対多の関係を持つ2つのエンティティがあります。ManyToManyでFetchType.LAZYを使用するには?

クラスの役割で:

@ManyToMany(mappedBy = "roles") 
private Set<User> users = new HashSet<>(); 

とクラスのユーザーで:

@ManyToMany 
@JoinTable(name = "role_user", joinColumns = @JoinColumn(name = "user_id"), 
     inverseJoinColumns = @JoinColumn(name = "role_id")) 
private Set<Role> roles = new HashSet<>(); 

そして、私は例外を取得:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: User.roles, could not initialize proxy - no Session

私はfetch = FetchType.EAGERを追加すると、私は別の例外を取得します:

java.lang.StackOverflowError: null

とロールとユーザーの間のサイクル。

この問題を解決するにはどうすればよいですか? Stackoverflowについても同様の質問がありましたが、私にとって本当の解決策は見つかりませんでした。

UPD:例外がスローされます :

@Service 
public class UserAuthenticationProvider implements AuthenticationProvider { 
    ... 

    @Override 
    @Transactional 
    public Authentication authenticate(final Authentication authentication) { 
     final String login = authentication.getName(); 
     final String password = authentication.getCredentials().toString(); 

     final User user = userRepository.findByLogin(login); 
     if (user != null && passwordEncoder.matches(password, user.getPassword())) { 
      return new UsernamePasswordAuthenticationToken(login, password, 
        user.getRoles()); // problem here 
     } else { 
      return null; 
     } 
    } 

    ... 
+0

あなたが提示した宣言に問題があるとは確信していません。あなたが報告した例外の1つまたは両方を再現できる[mcve]を提示してください。 –

答えて

1

Spring JPAを使用すると、JPQLでキーワード「JOIN FETCH」を試すと、遅延初期化例外を処理できます。 例

@Query("SELECT u FROM User u JOIN FETCH u.roles r WHERE r.roleId = :roleId AND u.userId=:userId") 
User findUserById(@Param("roleId") String roleId, @Param("userId") String userId); 
2

Hibernateはすでに理由を説明します:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: User.roles, could not initialize proxy - no Session

public List<Role> getRolesForUserId(int id){ 
    UserEntity user = userRepository.findUserById(1) 
    user.getRoles() 
} 

あなたが怠惰なフェッチを取得しようとしているので、これは、例外が発生しますアクティブな休止状態のセッションがないユーザーの役割

@Transactionalはあなたの友人です。 @Transactionalアノテーションは、Hibernateは、この方法の適用範囲のためにオープン同じセッションを維持するので、これは、動作する

@Transactional 
public List<Role> getRolesForUserId(int id){ 
    UserEntity user = userRepository.findUserById(1) 
    user.getRoles() 
} 

特定の範囲(例えば、方法)を用いてHibernateセッションを作成します。

+0

それは私を助けなかった。 '@ Transactional'アノテーションと' @ EnableTransactionManagement'を追加しましたが、何も変わりませんでした。 Beanで 'HibernateTransactionManager'と' SessionFactory'を設定した場合、見つけられなかった 'beanという名前のentityManagerFactory 'に関する例外があります。 他に何を試すことができますか? –

+0

@Herrの解決策に同意します。あなたのコレクションがセッションから切り離されているようです。モデルクラスでもアノテーションを更新できます。クラスのロールで、@ManyToMany(fetch = FetchType.LAZY、mappedBy = "roles")というアノテーションを更新し、Userクラスでそれを@ManyToMany(fetch = FetchType.LAZY、cascade = CascadeType.ALL)に更新します。 – Neero

+0

注釈を更新しましたが、役に立たなかった。私はこの答えを使用しようとしました:https://stackoverflow.com/a/30884155/8253837そして '@PeristenceContext private EntityManager em;'を '@ Transactional'メソッドのクラスに追加しました。これで' java.lang.StackOverflowError'例外。 また、私のUserRepositoryはCrudRepositoryを拡張します。 UserRepositoryを使う '@ Transactional'メソッドのためのクラスを作成しました。 –

関連する問題