Search code examples
spring-bootspring-data-restquerydsl

Filter results from QueryDSL search


I'm using QueryDSL as part of Spring Data Rest to search entities from our API.

Is it possible to somehow filter the search API, so that by default it won't find for example Car entities that are "deactivated"?

Currently I've a flag on car entity that when it's set to true, it shouldn't be exposed through our search API, and the cars that have this property set should be left out from search.

https://docs.spring.io/spring-data/jpa/docs/1.9.0.RELEASE/reference/html/#core.web.type-safe


Solution

  • In case of using Spring Data REST and QueryDSL, to change standard behavior of queries we can use aspects.

    For example: we need to show by default only those Models whose flag is set to true:

    @Data
    @NoArgsConstructor
    @Entity
    public class Model {
    
        @Id @GeneratedValue private Integer id;
        @NotBlank private String name;
        private boolean flag;
    }
    

    In this case we implement the aspect like this:

    @Aspect
    @Component
    public class ModelRepoAspect {
    
      @Pointcut("execution(* com.example.ModelRepo.findAll(com.querydsl.core.types.Predicate, org.springframework.data.domain.Pageable))")
      public void modelFindAllWithPredicateAndPageable() {
      }
    
      @Around("modelFindAllWithPredicateAndPageable()")
      public Object filterModelsByFlag(final ProceedingJoinPoint pjp) throws Throwable {
    
        Object[] args = pjp.getArgs();
        Predicate predicate = (Predicate) args[0];
    
        BooleanExpression flagIsTrue = QModel.model.flag.eq(true);
    
        if (predicate == null) {
            args[0] = flagIsTrue;
        } else {
            if (!predicate.toString().contains("model.flag")) {
                args[0] = flagIsTrue.and(predicate);
            }
        }
    
        return pjp.proceed(args);
      }
    }
    

    This aspect intercepts all calls of method findAll(Predicate predicate, Pageable pageable) of our repo, and add the filter model.flag = true to the query if the request parameters was not set (predicate == null), or if they don't contain 'flag' parameter. Otherwise aspect does not modify original predicate.