在Spring Data Query中的两个java.time.Instant实例之间获取记录

时间:2018-07-20 19:52:51

标签: hibernate jpa java-8 spring-data-jpa spring-data

我正在尝试使用Spring Data的@Query来获取两个Instant之间的记录列表。

 /**
   * Finds all the non-duplicate customers.
   * 
   * @return The list of non-duplicate customers.
   */
  //@formatter:off
  @Query("SELECT c "
      + "FROM Customer c "
      + "WHERE c.isDuplicate = false "
      + "  AND c.created BETWEEN :start AND :end "
      + "ORDER BY c.created")
  //@formatter:on
  List<Customer> findAllNonDuplicateCustomers(
      @Param("start") Instant start,
      @Param("end") Instant end
  );

在测试时,我发现:

this.customerRepository.findAllNonDuplicateCustomers(
    Instant.MIN, 
    Instant.MAX
)

返回一个空列表,但是:

this.customerRepository.findAllNonDuplicateCustomers(
    this.customers.get("rob").getCreated(), 
    this.customers.get("robba").getCreated()
)

返回所需的结果。

测试场景:

我的测试将6个客户插入到嵌入式H2数据库中,并尝试运行查询。

由于Instant是可比较的,并且对于确切的客户来说效果很好,所以使用Instant.MIN和Instant.MAX进行边界测试是否错误?

1 个答案:

答案 0 :(得分:1)

我创建了一个小示例项目,并为绑定参数启用了休眠记录,结果是:

binding parameter [1] as [TIMESTAMP] - [-1000000000-01-01T00:00:00Z]
binding parameter [2] as [TIMESTAMP] - [+1000000000-12-31T23:59:59.999999999Z]

可以看到,参数无需任何修改即可传递给数据库。数据库只是无法正确处理它,但显然可以处理更多“正常”值。

我认为这是一个错误或至少是JDBC驱动程序的限制。 我也尝试过使用HSQLDB。它具有类似的限制,但它不会返回空结果,而是会引发异常。

那你该怎么办:

  • 提交有关H2的问题。他们可能会添加检查并引发异常,但我怀疑他们会添加适当的支持。

  • 定义您自己的MINMAX实际有效的值。经过一些试验,从H2可以处理的角度来看,这似乎相当有效,并且很难提出现实世界中的场景,这些场景在将来/过去足够远。

    static final Instant CUSTOM_MIN = new Date(Long.MIN_VALUE / 2).toInstant();
    static final Instant CUSTOM_MAX = new Date(Long.MAX_VALUE / 2).toInstant();
    

注释:

There don't exist database independent min/max dates.

The minimum/maximum java.util.Date values here don't work either but obviously inspired my solution.