你可以使用过滤器,一个特定的 Hibernate 特性,来解决这个问题。
思路如下。
首先,您需要使用要应用的不同过滤器来注释您的实体,在您的情况下,例如:
@Entity
//...
@Filters({
@Filter(name="filterByGroup", condition="group_id = :group_id")
})
public class MyEntity implements Serializable {
// ...
}
然后,您需要访问底层EntityManager
,因为您需要与关联的 Hibernate 进行交互Session
。你有几种方法可以做到这一点。例如,您可以为任务定义自定义事务管理器,例如:
public class FilterAwareJpaTransactionManager extends JpaTransactionManager {
@Override
protected EntityManager createEntityManagerForTransaction() {
final EntityManager entityManager = super.createEntityManagerForTransaction();
// Get access to the underlying Session object
final Session session = entityManager.unwrap(Session.class);
// Enable filter
try{
this.enableFilterByGroup(session);
}catch (Throwable t){
// Handle exception as you consider appropriate
t.printStackTrace();
}
return entityManager;
}
private void enableFilterByGroup(final Session session){
final String group = this.getGroup();
if (group == null) {
// Consider logging the problem
return;
}
session
.enableFilter("filterByGroup")
.setParameter("group_id", group)
;
}
private String getGroup() {
// You need access to the user information. For instance, in the case of Spring Security you can try:
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
return null;
}
// Your user type
MyUser user = (MyUser)authentication.getPrincipal();
String group = user.getGroup();
return group;
}
}
然后,TransationManager
在你的数据库配置中注册这个而不是默认的JpaTransactionManager
:
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new FilterAwareJpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory());
return transactionManager;
}
您还可以通过创建自定义或通过注入您的 bean来访问EntityManager
和关联,但我认为上述方法是更简单的方法,尽管它具有总是被应用的缺点。Session
JpaRepository
@PersistenceContext