簡體   English   中英

如何將 FetchType.LAZY 與 ManyToMany 一起使用?

[英]How to use FetchType.LAZY with ManyToMany?

我有兩個具有多對多關系的實體。

在 class 中的作用:

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

在 class 用戶中:

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

我得到了例外:

org.hibernate.LazyInitializationException:延遲初始化角色集合失敗:User.roles,無法初始化代理 - 否 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;
        }
    }

    ...

Hibernate已經告訴你原因:

org.hibernate.LazyInitializationException:懶得初始化一個角色集合:User.roles,無法初始化代理 - 沒有Session

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

這將導致異常,因為您嘗試在沒有活動的hibernate會話的情況下獲取延遲獲取的用戶角色。

@Transactional是你的朋友。 @Transactional注釋將創建具有特定范圍的休眠會話(例如,方法)

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

這將起作用,因為hibernate會為此方法的范圍保持相同的會話打開。

使用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);

看起來@Transactional不適用於AuthenticationProvider的覆蓋方法。 我應該創建一個單獨的服務來處理這個問題。

這里有一個類似的答案: https://stackoverflow.com/a/23652569/8253837

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM