角色集合无法初始化代理-仅来自筛选器的无会话



我有一个关系ManyToMany:

@Entity
@Data
@Table(name = "usuarios")
public class Usuario implements Serializable{
...
@JsonIgnoreProperties({"usuario", "hibernateLazyInitializer", "handler"})
@ManyToMany(fetch=FetchType.LAZY, cascade = CascadeType.MERGE)
@JoinTable(name="usuarios_roles", 
joinColumns= @JoinColumn(name="usuario_id"),
inverseJoinColumns=@JoinColumn(name="role_id"),
uniqueConstraints = {@UniqueConstraint(columnNames = {"usuario_id","role_id"})})
private List<Role> role = new ArrayList<>();
...
}
@Entity
@Data
@Table(name = "roles")
public class Role implements Serializable{
.....
@JsonIgnoreProperties({"usuarios","hibernateLazyInitializer", "handler"})
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "role")
private List<Usuario> usuario = new ArrayList<>();
...
}

当我把它作为一个简单的rest运行时,它会完美地工作,它会返回用户和他的所有角色。

问题是当我从过滤器运行它时:

public class CustomFilter extends OncePerRequestFilter {
@Autowired
private IUsuarioService usuarioService;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
if(usuarioService == null){
ServletContext servletContext = request.getServletContext();
WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
usuarioService = webApplicationContext.getBean(IUsuarioService.class);
}
String[] path = request.getRequestURI().split("/");
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Usuario usuario = usuarioService.findByEmail(authentication.getName());
if(usuarioService.existsPermission(request.getMethod(), path[2], authentication.getName())) {
filterChain.doFilter(request, response);
} else {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}           
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}

服务是:

@Override
public Boolean existsPermission(String method, String rest, String email) {
Usuario usuario = usuarioDao.findByEmail(email);
Rest restcontroller = new Rest();
restcontroller = restDao.findByMetodoAndRestcontroller(method, rest);
for(Role role : usuario.getRole()) {
return restDao.existsPermission(restcontroller.getId(), role.getId());
}
return false;
}

此错误:

failed to lazily initialize a collection of role: iteam.ronald.project.models.entity.Usuario.role, could not initialize proxy - no Session

在调试模式下,getRole()返回以下错误:

Exception occurred: com.sun.jdi.InvocationException: Exception occurred in target VM occurred invoking method..

这让我认为我从这个过滤器启用userService的方式是不正确的。我错过了什么?

您收到此消息是因为您在事务外部调用usario.getRole,fetchType为LAZY。

要解决这个问题,您可以:

  • 将existsPermission放入事务或
  • 在通常情况下,Dao.findByEmail可以这样做:

代码示例:

public Usuario findByEmail(String email) {
Usuario usuario;
//fetch usuario
//load roles
usuario.getRole().size();
return usuario;
}

最新更新