有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用FetchType。和很多人一起偷懒?

我有两个具有多对多关系的实体

课堂角色:

@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;
        }
    }

    ...

共 (2) 个答案

  1. # 1 楼答案

    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()
    }
    

    这将导致一个异常,因为您试图在没有活动hibernate会话的情况下获取延迟获取的用户角色

    是你的朋友。@Transactional注释将创建具有特定范围(例如方法)的hibernate会话

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

    这将起作用,因为hibernate在这个方法的作用域内保持同一个会话的打开状态

  2. # 2 楼答案

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