首页 > 解决方案 > JPA - 使用 LocalDate 或 LocalDateTime 按日期获取

问题描述

我正在用 Spring 和 JPA 构建一个基本的酒店管理系统。我有一个名为 Order 的实体,它代表一个预订。它包含作为 LocalDateTime 的签入和签出日期:

private LocalDateTime checkin;
    
private LocalDateTime checkout;

我有一个 JPA 存储库 OrderRepository 链接到 Order。所有默认方法(查找、保存等)都可以正常工作。

我在“订单”表中有一些测试数据:

id room_id  checkin (DATETIME)          checkout (DATETIME) 
1     1     2020-06-08 00:00:00.000000  2020-06-09 00:00:00.000000
3     2     2020-06-09 00:00:00.000000  2020-06-19 00:00:00.000000
4     1     2020-06-09 00:00:00.000000  2020-06-19 00:00:00.000000

在我的 OrderRepository 中,我想要一种方法来获取与特定签入或签出日期匹配的所有订单。问题是,我无法使用'='。虽然它适用于'<'或'>'。

例如,拥有:

public interface OrderRepository extends JpaRepository<Order, Integer> {
    List<Order> findAllByCheckin(LocalDateTime checkin);
}

然后

LocalDateTime date = LocalDateTime.of(2020, 6, 9, 0, 0);        
List<Order> _orders = orderRepository.findAllByCheckin(date);

应该返回 2 个项目,但返回一个空列表

休眠日志输出:

Hibernate: select [...] from orders order0_ where order0_.checkin=?
o.h.type.descriptor.sql.BasicBinder: binding parameter [1] as [TIMESTAMP] - [2020-06-09T00:00]

当我对数据库手动运行完全相同的 SQL 时,我得到了正确的结果(2 行)

select * from orders order0_ where order0_.checkin='2020-06-09T00:00'

id room_id  checkin (DATETIME)          checkout (DATETIME)     
3   2       2020-06-09 00:00:00.000000  2020-06-19 00:00:00.000000
4   1       2020-06-09 00:00:00.000000  2020-06-19 00:00:00.000000

我还尝试使用 JPQL 手动定义查询。

@Query(value = "select o from Order o where o.checkin = :checkin")
List<Order> findAllByCheckin(@Param("checkin") LocalDateTime checkin);

休眠日志 - 与上面的相同:

Hibernate: select [...] from orders order0_ where order0_.checkin=?
o.h.type.descriptor.sql.BasicBinder: binding parameter [1] as [TIMESTAMP] - [2020-06-09T00:00]

结果相同 - 返回空列表。

有趣的是,当我将查询替换为 '<' 或 '>' 时,它可以正常工作:

@Query(value = "select o from Order o where o.checkin < :checkin")
List<Order> findAllByCheckin(@Param("checkin") LocalDateTime checkin);

按预期返回 1 个元素。

我究竟做错了什么?

我用:

感谢所有建议。

标签: mysqlhibernatejpalocaldatetime

解决方案


我得到了答案。MySQL 将所有条目存储为 UTC 时区,看起来 Hibernate 在查询数据库之前将 LocalDateTime 的值从我的本地时区转换为 UTC。因此,在我的情况下,存储“2020-06-09 00:00:00.000000”的 LocalDateTime 在查询中变为“2020-06-08 22:00:00.000000”,这解释了为什么“=”与这些记录不匹配。

也许有一些配置可以控制它,但看起来这是默认情况下的工作方式。


推荐阅读