JPA - выборка по дате с использованием LocalDate или LocalDateTime - PullRequest
0 голосов
/ 11 июля 2020

Я создаю базовую c систему управления отелем с помощью Spring и JPA. У меня есть объект под названием «Заказ», который представляет собой одно бронирование. Он содержит даты заезда и выезда как LocalDateTime:

private LocalDateTime checkin;
    
private LocalDateTime checkout;

У меня есть репозиторий JPA OrderRepository, связанный с Order. Все методы по умолчанию (find, save, et c) работают нормально.

У меня есть некоторые тестовые данные в таблице заказов:

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 я хотел иметь метод для получения всех заказов, соответствующих указанным c датам прибытия или отъезда. Проблема в том, что я не могу заставить его работать с '='. пока он отлично работает с '<' или '>'.

Например, имея:

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 элемент, как и ожидалось.

Что я делаю не так?

Я использую:

  • Spring Boot Starter JPA 2.2.6
  • MySQL

Спасибо за все предложения.

1 Ответ

0 голосов
/ 04 августа 2020

Я получил ответ. MySQL сохраняет все записи как UT C часовой пояс, и похоже, что Hibernate преобразует значение LocalDateTime из моего локального часового пояса в UT C перед запросом в БД. Итак, в моем случае LocalDateTime, хранящий «2020-06-09 00: 00: 00.000000», стал в запросе «2020-06-08 22: 00: 00.000000», что объясняет, почему '=' не соответствует этим записям.

Может быть, есть какая-то конфигурация для управления этим, но похоже, что это работает по умолчанию.

...