在Spring Data JPA存储库方法查询上附加自定义条件

我正在寻找一种将存储库类的所有findBy方法附加特定条件的方法

假设我有一个Product实体和一个Customer实体。它们都扩展了OwnerAwareEntity,并且它们都继承了ownerRef字段,该字段标识实体的所有者(它可以是商人或合作伙伴)。我想在运行时修改Product和Customer的findBy方法,以便将它们附加有ownerRef的附加条件。可以从用户会话中识别ownerRef值。

提供公共ownerRef字段的父实体类

public class OwnerAwareEntity implements Serializable {

private String ownerRef;

}

扩展OwnerAwareEntity的客户实体

public class Customer extends OwnerAwareEntity {

private String firstname;

private String mobile ;

}

扩展OwnerAwareEntity的产品实体

public class Product extends OwnerAwareEntity {

private String code;

private String name;

}

产品和客户的存储库类,用于扩展OwnerAwareRepository

public interface OwnerAwareRepository extends JpaRepository {

}

public interface ProductRepository extends OwnerAwareRepository {

Product findByCode(String code );

}

public interface CustomerRepository extends OwnerAwareRepository {

Customer findByFirstname(String firstname );

}

当执行时,这将导致如下查询

select P from Product P where P.code=?1 and P.ownerRef='aValue'

&

select C from Customer C where C.firstname=?1 and C.ownerRef='aValue'

要实现这种条件附加,我应该采取什么方法?我只希望在父存储库为OwnerAwareRepository时进行此追加。

回答:

我使用了Hibernate的@Filter,然后创建了一个Aspect来拦截方法

定义具有以下结构的基类实体

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的实体定义基础存储库

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.repository.NoRepositoryBean;

@NoRepositoryBean

public interface OwnerAwareRepository<T, ID extends java.io.Serializable> extends JpaRepository<T, ID> {

}

创建了一个Aspect将拦截扩展OwnerAwareRepository的存储库中的所有方法

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

@Slf4j

public 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 {

}

这些文件放置到位后,您需要对需要了解所有者的实体执行以下操作

  1. 该实体需要扩展OwnerAwareEntity
  2. 实体存储库类需要扩展OwnerAwareRepository

此设置要求spring aop处于依赖关系中。您可以将以下内容添加到pom.xml中

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-aop</artifactId>

</dependency>

  1. 适用于所有选择查询(findBy方法,findAll等)
  2. @Query方法也被拦截
  3. 实施简单

  • 删除或更新的where子句不受

    此过滤器的影响。

  • 如果存储库包含一个save / update / delete方法,并且该

    方法未标记为@Transactional,则拦截器将给出

    错误信息(在这种

    情况下,您可以捕获并让方法正常进行)

以上是 在Spring Data JPA存储库方法查询上附加自定义条件 的全部内容, 来源链接: utcz.com/qa/411233.html

回到顶部