2

I'm using QuerydslPredicate in my RestController on an entity which has a date object, I want to be able to query for a date before/after/between given dates, hoping to have something like

  • GET /problems?createdOnAfter=XXX
  • GET /problems?createdOnBefore=YYY
  • GET /problems?createdOnAfter=XXX&createdOnBefore=YYY

My entity has the date field createdOn and I was hoping I could customise bindings for an entity path using multiple aliases i.e. adding aliases createdOnAfter & createdOnBefore - it doesn't look like I can create multiple aliases though, e.g.

@Repository
public interface ProblemRepository extends JpaRepository<Problem, String>, QueryDslPredicateExecutor<Problem>,
        QuerydslBinderCustomizer<QProblem> {

            ....

    @Override
    default void customize(QuerydslBindings bindings, QProblem root) {
        bindings.bind(root.createdOn).as("createdOnAfter").first(TemporalExpression::after);
        bindings.bind(root.createdOn).as("createdOnBefore").first(TemporalExpression::before);
    }
}

The before alias is obviously overwriting the after one.

What's the correct approach to avoid having to manually create the predicates?

Bacon
  • 1,229
  • 2
  • 14
  • 26
  • check this https://stackoverflow.com/a/35158320/5380322 ... – Cepr0 Nov 21 '17 at 10:02
  • 1
    I was hoping to be able to use createdOnAfter, createdOnBefore or both - that solution means I have to supply 2 dates everytime – Bacon Nov 22 '17 at 11:23

2 Answers2

2

Why not using QueryDSL Predicate ? You could do :

@GetMapping("/problems")
@Timed
public ResponseEntity<List<ProblemDTO>> getAllProblems(
      @RequestParam(required = false) LocalDateTime createdOnAfter, 
      @RequestParam(required = false) LocalDateTime createdOnBefore,
      @ApiParam Pageable pageable) {
    BooleanBuilder where = new BooleanBuilder();
    if (startDate != null) {
        where = where.and(problem.createdOn.after(createdOnAfter));
    }
    if (endDate != null) {
        where = where.and(problem.createdOn.before(createdOnBefore));
    }
    Page<Donnee> page = problemRepository.findAll(where, pageable);
    return new ResponseEntity<>(problemMapper.toDTO(page.getContent())), null, HttpStatus.OK);
}

Hope it helps, Regards

teikitel
  • 700
  • 5
  • 16
  • 1
    Well, it surely helps, if you have limited number of options. But this is not an aswer but a workaround. Is there a correct way to specify multiple "aliases" or "predicated" per single field? – Sergey Oct 21 '19 at 15:02
0

How about adding new Entity properties and marking those as transient like this:

@Transient
private Instant createdOnBefore;
@Transient
private Instant createdOnAfter;

and then customise your repository class like this:

@Override
default void customize(final QuerydslBindings bindings, final QProblem  root) {
    bindings.bind(root.createdOnBefore).first((path, value) -> root.createdOn.goe(value));
    bindings.bind(root.createdOnAfter).first((path, value) -> root.createdOn.loe(value));
}
theo
  • 915
  • 1
  • 9
  • 28