Получение записей МЕЖДУ двумя экземплярами java.time.Instant в Spring Data Query

Я пытаюсь получить список записей между двумя Instant, используя Spring Data @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(
    Instant.MIN, 
    Instant.MAX
)

возвращает пустой список, но:

this.customerRepository.findAllNonDuplicateCustomers(
    this.customers.get("rob").getCreated(), 
    this.customers.get("robba").getCreated()
)

возвращает желаемые результаты.

Сценарий тестирования:

Мой тест вставляет 6 клиентов во встроенную базу данных H2 и пытается выполнить запрос.

Поскольку Instant совместим и отлично работает для конкретных клиентов, неправильно ли использовать Instant.MIN и Instant.MAX для пограничного тестирования?

Мне это кажется ошибкой. В настоящее время я просто не уверен, виноваты ли в этом Spring Data, Hibernate или драйвер JDBC.

Jens Schauder 21.07.2018 09:20

вот идея. Вы смотрите на SQL, вызванный провайдером JPA ...

user3973283 21.07.2018 11:05

SQL не поможет, поскольку он просто будет содержать параметры привязки. Но регистрация переданных значений может дать некоторое представление.

Jens Schauder 21.07.2018 11:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
1 568
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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();
    

Заметки:

Не существует независимых от базы данных минимальных / максимальных дат.

Минимальные / максимальные значения java.util.Date здесь тоже не работают, но, очевидно, вдохновили меня на решение.

Я преобразовал java.time.Instant в java.sql.Timestamp, используя метод Timestamp.from (Instant). Я получил следующее: `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 `

sidmishraw 22.07.2018 09:52

Продолжая предыдущий комментарий, когда я делаю present.after(past) –– где настоящее - это Timestamp.from (Instant.now ()), а прошлое - это Timestamp.from (Instant.MIN) –– я получаю false. Может ли это быть способствующим фактором? P.S. Документ javadoc для Timestamp # after (Timestamp) читает: Указывает, является ли этот объект Timestamp более поздним, чем данный объект Timestamp.

sidmishraw 22.07.2018 10:02
past.after(present) дает true.
sidmishraw 22.07.2018 10:04

# Продолжаем # Тем не менее, моделирование с помощью примера ниже Timestamp present_1 = Timestamp.from(Instant.now());Thread.sleep(1000);Timestamp present_2 = Timestamp.from(Instant.now());System.out.println("is present2 after present1 = " + present_2.after(present_1)); // trueSystem.out.println("is present1 after present2 = " + present_1.before(present_2)); // true дает ожидаемые результаты.

sidmishraw 22.07.2018 10:09

Поскольку H2 написан на Java, это может быть причиной, но это всего лишь предположение с моей стороны.

Jens Schauder 22.07.2018 11:07

Другие вопросы по теме