
TL; DR: 我使用了Hibernate的@Filter,然后创建了一个Aspect来拦截方法
定义具有以下结构的基类实体
OwnerAwareEntity.java
import org.hibernate.annotations.Filter;import org.hibernate.annotations.FilterDef;import org.hibernate.annotations.ParamDef; import javax.persistence.Column;import javax.persistence.MappedSuperclass;import java.io.Serializable;@MappedSuperclass@FilterDef(name = "ownerFilter", parameters = {@ParamDef(name = "ownerRef", type = "long")})@Filter(name = "ownerFilter", condition = "OWNER_REF = :ownerRef")public class OwnerAwareEntity implements Serializable{ @Column(name = "OWNER_REF",nullable = true) private Long ownerRef;}我们对此实体设置过滤器。hibernate@Filter允许我们设置要附加到select where子句的条件。
接下来,为类型OwnerAwareEntity的实体定义基础存储库
OwnerAwareRepository.java
import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.repository.NoRepositoryBean;@NoRepositoryBeanpublic interface OwnerAwareRepository<T, ID extends java.io.Serializable> extends JpaRepository<T, ID> {}创建了一个Aspect将拦截扩展OwnerAwareRepository的存储库中的所有方法
OwnerFilterAdvisor.java
import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.hibernate.Filter;import org.hibernate.Session;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;@Aspect@Component@Slf4jpublic class OwnerFilterAdvisor { @PersistenceContext private EntityManager entityManager; @Pointcut("execution(public * com.xyz.app.repository.OwnerAwareRepository+.*(..))") protected void ownerAwareRepositoryMethod(){ } @Around(value = "ownerAwareRepositoryMethod()") public Object enableOwnerFilter(ProceedingJoinPoint joinPoint) throws Throwable{ // Variable holding the session Session session = null; try { // Get the Session from the entityManager in current persistence context session = entityManager.unwrap(Session.class); // Enable the filter Filter filter = session.enableFilter("ownerFilter"); // Set the parameter from the session filter.setParameter("ownerRef", getSessionOwnerRef()); } catch (Exception ex) { // Log the error log.error("Error enabling ownerFilter : Reason -" +ex.getMessage()); } // Proceed with the joint point Object obj = joinPoint.proceed(); // If session was available if ( session != null ) { // Disable the filter session.disableFilter("ownerFilter"); } // Return return obj; } private Long getSessionOwnerRef() {// Logic to return the ownerRef from current session }}顾问程序设置为拦截扩展OwnerAwareRepository的类中的所有方法。在侦听时,从(当前持久性上下文的)entityManager获取当前的hibernate会话,并使用参数值“
ownerRef”启用过滤器。
还创建一个配置文件以扫描顾问程序
import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@Configuration@ComponentScan(basePackages = {"com.xyz.app.advisors"})public class AOPConfig {}这些文件放置到位后,您需要对需要了解所有者的实体执行以下操作
依存关系
此设置要求spring aop处于依赖关系中。您可以将以下内容添加到pom.xml中
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId></dependency>
优点
注意事项
删除或更新的where子句不受
此过滤器的影响。
如果存储库包含一个save / update / delete方法,并且该
方法未标记为@Transactional,则拦截器将给出
错误信息(在这种
情况下,您可以捕获并让方法正常进行)