我在使用 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()
,并且可以正常工作,因为它已经初始化并且不再需要连接到数据库。
始终了解您的交易从何处开始和结束。
根据您的用例,您可能还会考虑使用 OpenEntityManagerInViewFilter或 OpenEntityManagerInViewInterceptor (或 native Hibernate
API OpenSessionInViewFilter/Intercetor
的等效项),但是 read about consequences first .
请告诉我类(class)名称中的KZ
不是您的姓名首字母吗?如果他们是,请,请,请不要那样做...
关于java - 使用 Spring 错误的 Hibernate 一对多映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22576633/