Hibernate 在Spring数据查询中获取两个java.time.Instant实例之间的记录

Hibernate 在Spring数据查询中获取两个java.time.Instant实例之间的记录,hibernate,jpa,java-8,spring-data-jpa,spring-data,Hibernate,Jpa,Java 8,Spring Data Jpa,Spring Data,我正在尝试使用Spring数据的@Query获取两个瞬间之间的记录列表 /** * 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

我正在尝试使用Spring数据的
@Query
获取两个瞬间之间的记录列表

 /**
   * 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(
    this.customers.get("rob").getCreated(), 
    this.customers.get("robba").getCreated()
)
返回所需的结果

测试场景:

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


由于Instant具有可比性,并且适用于精确的客户,因此使用Instant.MIN和Instant.MAX进行边界测试是否错误?

我创建了一个小示例项目,并启用了绑定参数的hibernates日志记录,从而导致:

binding parameter [1] as [TIMESTAMP] - [-1000000000-01-01T00:00:00Z]
binding parameter [2] as [TIMESTAMP] - [+1000000000-12-31T23:59:59.999999999Z]
正如我们可以看到的那样,参数在没有任何修改的情况下被传递到数据库。数据库无法正确处理它,但它显然可以处理更多的“正常”值

我认为它是一个bug,或者至少是JDBC驱动程序的一个限制。 我也用HSQLDB试过了。它也有类似的限制,但它不会返回空结果,而是抛出异常

那么你能做什么:

  • 提交一个带有H2的问题。他们可能会添加检查并抛出异常,但我怀疑他们是否会添加适当的支持

  • 定义您自己的实际工作的
    MIN
    MAX
    值。经过一点实验后,这似乎工作得相当好,因为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();
    
注:


我觉得这听起来像个虫子。我目前只是不确定是Spring数据、Hibernate还是JDBC驱动程序造成的。看看JPA提供程序调用的SQL……SQL不会有帮助,因为它只包含绑定参数。但是记录传递的值可能会提供一些见解。我使用Timestamp.from(Instant)方法将java.time.Instant转换为java.sql.Timestamp。我得到了以下信息:`Timestamp.from(Instant.MIN)=169108098-07-03 21:51:43.0 Timestamp.from(Instant.MAX)=169104627-12-11 11:08:15.999999999 Timestamp.from(Instant.now())=2018-07-22 00:46:17.518`当我执行
present.after(pass)
–其中present是Timestamp.from(Instant.now())过去是时间戳。从(Instant.MIN)–我得到
false
。这可能是一个促成因素吗?另外,Timestamp#after(Timestamp)的javadoc读取:指示此Timestamp对象是否晚于给定的Timestamp对象。
pass.after(present)
gives
true
。#继续#但是,使用下面的示例模拟它
Timestamp present\u 1=Timestamp.from(Instant.now())线程睡眠(1000)
Timestamp present_2=Timestamp.from(Instant.now())
System.out.println(“在呈现1之后是呈现2=“+present_2.after(present_1));//true
System.out.println(“在present2之后是present1=“+present_1.before(present_2));//true
提供了预期的结果。因为H2是用Java编写的,这可能就是原因,但这只是我的猜测。
static final Instant CUSTOM_MIN = new Date(Long.MIN_VALUE / 2).toInstant();
static final Instant CUSTOM_MAX = new Date(Long.MAX_VALUE / 2).toInstant();