JPA 查询以在可选的开始日期和结束日期之前、之后和之间进行过滤

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

我想编写一个 JPA 存储库查询,可以 findBy 使用两个可选查询参数,startDateendDate:

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

如何简洁地实现?例如,使用带有可以处理 nullOptional<Date> 参数的 SQL 语句的单个 JPA @Query 方法?

编辑:我正在使用 PostgreSQL 13.

您可以使用以下查询来实现此目的。我可以自由使用 <=>=,但当然您可以选择 <> 或两者之一。这个想法是已经为您提供了一个有效的查询。

@Query("SELECT m FROM MyObject m WHERE (:beforeDate is null or m.beforeDate >= :beforeDate) and (:afterDate is null or m.afterDate <= :afterDate)")
List<MyObject> findByDateBetween(Date beforeDate, Date afterDate);

这是一个简单的解决方案,使用 4 种方法和一个开关。它很笨重,但它确实有效。如果需要实现更复杂的 JPQL 或 SQL 查询,这种方法可能会变得特别冗长,因为需要复制 4 个存储库方法和查询。

存储库

@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();

服务

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);
  }
}

(Marc Gravell 的 answer 开关编码归功于此)