我正在编写一个简单的Spring启动应用程序。
对于身份验证部分,我实现了自定义UserDetails。当我向登录端点发出请求时,我得到了这个例外:
Authentication Failed: failed to lazily initialize a collection of role: com.boot.cut_costs.config.security.CustomUserDetails.roles, could not initialize proxy - no Session
CustomUserDetails.java
@Entity
@Table(name="ACCOUNT_USER")
public class CustomUserDetails implements UserDetails {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "USER_ID")
private long id;
@NotBlank
@Column(name = "USERNAME")
private String username;
@NotBlank
@Column(name = "PASSWORD")
private String password;
@Column(name = "LOCKED")
private boolean locked;
@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name = "USER_ROLE",
joinColumns = @JoinColumn(name = "USER_ID"),
inverseJoinColumns = @JoinColumn(name = "ROLE_ID"))
private Set<CustomRole> roles;
public CustomUserDetails(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<GrantedAuthority> authorities) { // jpa only
this.setUsername(username);
this.setPassword(password);
this.roles = new HashSet<CustomRole>();
for (GrantedAuthority authority: authorities) {
roles.add(new CustomRole(authority.getAuthority()));
}
}
public CustomUserDetails() { // jpa only
}
@Override
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Set<CustomRole> getRoles() {
return roles;
}
public void setRoles(Set<CustomRole> roles) {
this.roles = roles;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
ArrayList<String> authoritiesList = new ArrayList<String>();
for (CustomRole role: roles) {
authoritiesList.add(role.getRole());
}
return AuthorityUtils.commaSeparatedStringToAuthorityList(String.join(",", authoritiesList));
}
//Some more getters and setters ...
}
CustomRole.java
@Entity
@Table(name="ACCOUNT_ROLE")
public class CustomRole {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ROLE_ID")
private long id;
@Column(name="ROLE")
private String role;
public long getId() {
return id;
}
//delete if not necessary
public void setId(long id) {
this.id = id;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public CustomRole() {} //for jpa
public CustomRole(String role) {
this.role = role;
}
}
当我在Eager
注释中创建获取类型ManyToMany
时,它可以正常工作。
我读到这是不好的做法。首先,我想知道为什么?第二,我想知道什么是好的做法?我在这里混合服务层和DAO吗?
答案 0 :(得分:2)
当您使用 Lazy 时,您加载的用户没有角色,角色只会在您使用时收费
这里你使用了 spring security ,当你调用CustomUserDetails时,你应该把 Eager 加载所有角色, 在一般情况下使用Eager并不是一个好习惯,因为您加载了许多不需要它们的细节