通常,我们在服务器中有一个使用Spring Boot 2.0.2(包含Spring Data和Spring Security)的客户端服务器应用程序。
我们有一个具有以下实现的自定义用户对象:
@Entity
@Table(name="USERS")
public class User implements Serializable {
@Id
@Column(name="ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name="USERNAME", unique = true)
private String username;
@Column(name="PASSWORD")
private String password;
@ManyToMany(fetch = FetchType.LAZY)
@Cascade(CascadeType.SAVE_UPDATE)
@JoinTable
(
name="USER_INITSTATES",
joinColumns={ @JoinColumn(name="USER_ID", referencedColumnName="ID") },
inverseJoinColumns={ @JoinColumn(name="INITSTATE_ID", referencedColumnName="ID") }
)
private List<InitState> initStates = new ArrayList<>();
public List<InitState> getInitStates() {
return initStates;
}
}
我们有以下实现用于检索当前登录用户的InitState
(客户端的某种配置对象):
@PostFilter("false")
public List<InitState> loadActiveUserInitStates() {
if (SecurityContextHolder.getContext().getAuthentication() != null) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
User user = userService.findByUsername(currentPrincipalName);
return user.getInitStates();
}
return null;
}
有问题的部分是我们返回user.getInitStates()
的地方。由于User.initStates
变量是用FetchType.LAZY
配置的,因此hibernate / jpa将列表作为持久性包返回。现在,当Spring Security通过@PostFilter
注释在检索后评估列表时,它将遍历该列表并过滤掉未授予访问权限的对象(当然,我们有一个比false
更复杂的表达式,但是例如,它会做到)。当过滤后的列表返回给调用者时,hibernate希望保留该列表,并从InitStates
对象中删除所有User
引用。
我的两个问题是: *为什么Hibernate在没有任何显式调用的情况下保留列表?是否有任何有关此行为的文档? *(如何)我可以配置/禁用此行为?