Search code examples
javasqlpostgresqlspring-data-jpaspring-repositories

JPA query to filter before, after and between optional start and end dates


I'd like to write a JPA Repository query that can findBy with two optional query parameters, startDate and endDate:

startDate endDate Return
null null All
null endDate Before End
startDate null After Start
startDate endDate Between Start and End

How can this be implemented concisely? For example, using a single JPA @Query method with a SQL statement that can handle null or Optional<Date> parameters?

EDIT: I'm using PostgreSQL 13.


Solution

  • Here's a naïve solution using 4 methods and a switch. It's clunky, but it works. This approach can get particularly verbose if more complex JPQL or SQL queries need to be implemented, since the 4 Repository methods and queries would need to be duplicated.

    Repository

    @Repository
    public interface MyRepository extends JpaRepository<MyObject> {
      List<MyObject> findByDateBetween(Date beforeDate, Date afterDate);
      List<MyObject> findByDateBefore(Date beforeDate);
      List<MyObject> findByDateAfter(Date afterDate);
      List<MyObject> findAll();
    

    Service

    public List<MyObject> search(Date startDate, Date endDate) {
      int i = (startDate!=null ? 1 : 0) | (endDate!=null ? 2 : 0);
      switch(i) {
        case 0:
          return repository.findAll();
        case 1:
          return repository.findByDateAfter(startDate);
        case 2:
          return repository.findByDateBefore(endDate);
        case 3:
          return repository.findByDateBetween(startDate, endDate);
      }
    }
    

    (credit to this answer by Marc Gravell for the switch encoding)