Hibernate 在Spring数据查询中获取两个java.time.Instant实例之间的记录
我正在尝试使用Spring数据的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
@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
值。经过一点实验后,这似乎工作得相当好,因为H2可以处理它,并且很难想出在未来/过去足够远的真实场景MAX
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)
givestrue
。#继续#但是,使用下面的示例模拟它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();