我使用 Spring 框架,在从多对多表映射角色集时遇到问题。让我向您展示我的课程。
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NonNull
private String authority;
@ManyToMany(mappedBy = "roles", fetch = FetchType.EAGER/*, cascade=CascadeType.MERGE*/)
private Set<AppUser> appUsers;
public Role(@NonNull String authority) {
this.authority = authority;
}
public Role() {
}
}
public class AppUser implements Serializable {
@Serial
private static final long serialVersionUID = -8357820005040969853L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// @NonNull
@Column(unique = true)
private /*final*/ String username;
// @NonNull
private /*final*/ String password;
@ManyToMany(fetch = FetchType.EAGER/*, cascade=CascadeType.MERGE*/)
// @NonNull
@JoinTable(name = "users_roles",
joinColumns = @JoinColumn(name = "role_id"/*, referencedColumnName = "id"*/),
inverseJoinColumns = @JoinColumn(name = "user_id"/*, referencedColumnName = "id"*/))
private Set<Role> roles;
}
以下是保存过程:
@Bean
// @Transactional
public CommandLineRunner run(RoleRepository roleRepository, UserRepository userRepository, PasswordEncoder passwordEncoder) {
return args -> {
if (roleRepository.findByAuthority("ADMIN").isEmpty()) {
Role admin = roleRepository.save(new Role("ADMIN"));
Role user = roleRepository.save(new Role("USER"));
userRepository.save(new AppUser("admin", passwordEncoder.encode("admin"), new HashSet<>() {
{
add(admin);
add(user);
}
}));
}
};
}
这是我想要检索用户角色的时刻:
@Component
public class UserInterceptor implements HandlerInterceptor {
private final UserRepository userRepository;
private final RoleRepository roleRepository;
public UserInterceptor(UserRepository userRepository, RoleRepository roleRepository) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
}
@Override
public void postHandle(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull Object handler,
ModelAndView modelAndView) {
if (modelAndView != null) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Optional<AppUser> appUser = userRepository.findByUsername(authentication.getName());
if (appUser.isPresent()) {
Set<Role> set = roleRepository.findByAppUsers(new HashSet<>() {
{
add(appUser.get());
}
});
log.info("Roles for user {}: {}", appUser.get().getUsername(), appUser.get().getRoles());
modelAndView.addObject("username", appUser.get().getUsername());
modelAndView.addObject("roles", appUser.get().getRoles());
} else
modelAndView.addObject("username", "anonymous");
}
}
}
最有趣的部分是,当我以“admin”身份使用密码“admin”登录系统时,它会在数据库中看到我的用户,并且我实际上在可选 appUser 中具有值。检查存在后,我创建简单的集只是为了检查它是否映射特定用户的角色,之后我就拥有了由 User 对象检索的角色集。
现在神奇的部分来了:如果我尝试从执行 appUser.get().getRoles() 的用户获取角色,我会在 appUser 对象中得到空的角色集。我的意思是,我可以尝试使用由 userRepository.findByUsername 创建的额外集来获取所有角色,但我觉得它不应该以这种方式工作。任何人都可以帮助我吗,我将不胜感激,它将帮助我获得 Spring 框架。提前致谢。 附:这是数据库中的表,是的,列名弄乱了,我已经修复了它。
您似乎在 Hibernate 中遇到了延迟初始化问题,特别是在获取集合时发生。
您可以使用
@Fetch(FetchMode.JOIN)
将获取策略从惰性更改为急切。
@ManyToMany(fetch = FetchType.EAGER)
@Fetch(FetchMode.JOIN)
@JoinTable(name = "users_roles",
joinColumns = @JoinColumn(name = "role_id"),
inverseJoinColumns = @JoinColumn(name = "user_id"))
private Set<Role> roles;
请注意,应谨慎执行此操作,因为它可能会产生许多影响,例如性能下降。