java - 使用 Spring 错误的 Hibernate 一对多映射

标签 java spring hibernate session

我在使用 Hibernate 和 Spring 时遇到了这个问题 无法延迟初始化一个集合 : , no session or session was closed using one-to-many relationship 我有两个表,一个是来自用户的用户和角色我正在尝试使用延迟获取来获取角色。 堆栈跟踪

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.rep.users.KZ_Users.roleList, no session or session was closed
    org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
    org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
    org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
    org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
    org.hibernate.collection.PersistentList.iterator(PersistentList.java:115)
    com.rep.users.KZ_Users.getAuthorities(KZ_Users.java:137)
    org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.createSuccessAuthentication(AbstractUserDetailsAuthenticationProvider.java:186)
    org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:165)
    org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:120)
    org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:48)
    org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:138)
    org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:48)
    org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:97)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:109)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)

我已经在我的 KZ_Users pojo 类中实现了 UserDetails 和 Serializable 导致错误的方法是

@Override
    public Collection<GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();

        for (Roles roles : roleList) { //<-- ERROR 
            list.add(new GrantedAuthorityImpl(roles.getRole()));
        }

        return list;
    }

角色列表在 KZUser 类中定义。 谁能告诉我问题出在哪里 错误是

 16:15:01,317 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/ReportingPortalV3].[default]] (http-/192.168.1.124:8080-2) JBWEB000236: Servlet.service() for servlet default threw exception: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.rep.users.KZ_Users.roleList, no session or session was closed

提前致谢。

最佳答案

Spring 特定的 API 与您的实体分开。不要在你的 @Entity 类中直接实现 UserDetails 接口(interface),而是扩展它(或组合),即:

public class CurrentUser extends User implements UserDetails {

    private final Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();

    public CurrentUser(User user) {
        super(user);
        initAuthorities(user);
    }

    private void initAuthorities(User user) {
        if (user.getRoles() == null) {
            return;
        }
        for (Authority role : user.getRoles()) {
            authorities.add(new SimpleGrantedAuthority(role.getAuthority()));
        }
    }

    @Override
    public Collection<GrantedAuthority> getAuthorities() {
        return authorities;
    }

    // implement the rest of UserDetails interface accordingly
}

同时在构造函数中保留 authorities 集合的初始化。然后:

public class UserDetailsServiceImpl extends UserDetailsService {

    @Override
    @Transactional(propagation = SUPPORTS, readOnly = true)
    public CurrentUser loadUserByUsername(String username) 
            throws AuthenticationException ,DataAccessException {
        ensureNotEmpty(username);
        User user = userRepository.findUserWithAuthorities(username);
        if (user == null) {
            throw new UsernameNotFoundException("Invalid credentials!");
        }
        return new CurrentUser(user);
    }
}

请注意,通过这种方式,您将访问 roles 集合,该集合仍然标记为我的 @Transactional 的交易中。现在 Spring 可以在需要的地方调用 getAuthorities(),并且可以正常工作,因为它已经初始化并且不再需要连接到数据库。

始终了解您的交易从何处开始和结束

根据您的用例,您可能还会考虑使用 OpenEntityManagerInViewFilterOpenEntityManagerInViewInterceptor (或 native Hibernate API OpenSessionInViewFilter/Intercetor 的等效项),但是 read about consequences first .

请告诉我类(class)名称中的KZ 不是您的姓名首字母吗?如果他们是,请,请,请不要那样做...

关于java - 使用 Spring 错误的 Hibernate 一对多映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22576633/

相关文章:

javascript - AJAX 调用后未找到 404

java - 无法进入我的 spring boot Controller 方法

java - 使用 Spring Integration JDBC 出站网关更新数据

java - 如何在多对多关联表上编写查询

java - 一次进行 1、2 或 3 步到第 n 步的组合数‽

java - 如何在 Java 中简化这段代码?

java - 是否可以使用 HashMultimap 创建 spring bean?

java - 如何使用多对多字段原生查询 WHERE IN?

java - JPA 实体管理器资源处理

java - JPA "contains one of"