Литерал временной метки в JPQL-типизированном запросе с Hibernate - PullRequest
0 голосов
/ 25 апреля 2018

Есть ли способ использовать литералы меток времени в запросах JPQL с Hibernate?

Существует постоянная временная метка для сравнения, которая должна быть помещена в JPQL-запрос. Теперь это работает так

TypedQuery<TestEntity> query = entityManager
.createQuery("select t from TestEntity t where greatest(nvl(t.f1, :nullDate), nvl(t.f2, :nullDate)) between :date1 and :date2")
.setParameter("date1", date1)
.setParameter("date2", date2)
.setParameter("nulllDate", LocalDateTime.of(1970, 1, 1, 0, 0, 0, 1))

Я пытался (решение найдено здесь и здесь ) изменить запрос на следующий

select t from TestEntity t where greatest(nvl(t.f1, {ts '1970-01-01 00:00:00:000000001'}), nvl(t.f2, {ts '1970-01-01 00:00:00:000000001'})) between :startChanges and :endChanges

но получил ошибку во время выполнения

org.hibernate.QueryException: unexpected char: '{' [select t from TestEntity t where greatest(nvl(t.f1, {ts '1970-01-01 00:00:00:000000001'}), nvl(t.f2, {ts '1970-01-01 00:00:00:000000001'})) between :startChanges and :endChanges]

Моя настройка
Java 8
JPA 2,1
Spring Boot 1.4.2.RELEASE
Hibernate 5.1.0.Final (воспроизводится также с 5.2.16.Final)
Oracle 11.2

UPD: возможно, это не соответствует спецификации, но самые большие функции / nvl правильно передаются из JPQL в SQL с помощью приведенного выше кода. Я пытался обернуть greatest / nvl в function, но литералы по-прежнему не принимаются.

1 Ответ

0 голосов
/ 25 апреля 2018

Я подготовил тест в своей среде, и он возвращает результаты:

Calendar calendar = Calendar.getInstance();
calendar.setTime(date1);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

date1 = calendar.getTime();

calendar.setTime(date2);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

date2 = calendar.getTime();

TypedQuery<TestEntity> query = entityManager
.createQuery("select t from TestEntity t where greatest(nvl(t.f1, TO_TIMESTAMP('1970-01-01 00:00:00,000000001', 'YYYY-MM-DD HH24:MI:SS,FF9')), nvl(t.f2, TO_TIMESTAMP('1970-01-01 00:00:00,000000001', 'YYYY-MM-DD HH24:MI:SS,FF9')) between :date1 and :date2")
.setParameter("date1", date1)
.setParameter("date2", date2);

Надеюсь, это то, что вы ищете.

РЕДАКТИРОВАТЬ: Модифицированный запрос для добавления TO_TIMESTAMP функции. Подтверждено @dfche это работает

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...