我正在尝试使用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进行边界测试是否错误?
答案 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的问题。他们可能会添加检查并引发异常,但我怀疑他们会添加适当的支持。
定义您自己的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();
注释:
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.