Дата операции в HQL
Я хочу получить просроченные объекты из таблицы, используя HQL. Что-то вроде того:
select id, name from entity_table where date_creation + 10_minutes < current_time()
Я не могу понять, как это сделать с HQL. Я не хочу делать дополнительные запросы, обрабатывать дату в коде Java и так далее. Это должно быть сделано на уровне HQL.
Не могли бы вы мне помочь?
3 ответа
В зависимости от вашей базы данных это может быть тривиально просто. HQL поддерживает встроенные специфичные для поставщика функции и функции, а также поддерживает возможность расширения диалекта путем регистрации новых функций, если они еще не поддерживаются HQL.
Допустим, вы используете SQLServer (или Sybase). В SQLServer есть функция DATEADD, которая может делать то, что вам нравится, очень легко. Формат такой:
DATEADD (datepart, number, date)
Вы можете использовать эту функцию непосредственно в HQL, предварительно зарегистрировав функцию на своем собственном диалекте Hibernate. Для этого вам просто нужно расширить диалект, который вы сейчас используете. Это очень простой процесс.
Сначала создайте свой собственный класс диалекта (замените "SQLServer2008Dialect" на вашего собственного поставщика БД):
public class MySQLServerDialect extends SQLServer2008Dialect {
public MySQLServerDialect() {
registerFunction("addminutes", new VarArgsSQLFunction(TimestampType.INSTANCE, "dateadd(minute,", ",", ")"));
}
}
Затем измените вашу конфигурацию гибернации, чтобы использовать этот новый класс:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
...
<property name="hibernate.dialect">com.mycompany.MySQLServerDialect</property>
...
</hibernate-configuration>
Теперь просто используйте функцию:
select x from MyEntity x where addminutes(x.creationDate, 10) < current_time()
(Предполагается, что ваша сущность называется MyEntity, а поле creation_date сопоставлено со свойством creationDate).
HQL не поддерживает арифметику с датой и временем, поэтому без расширения HQL это невозможно. Самый простой путь, вероятно, состоит в том, чтобы зарегистрировать базу данных поставщиков SQL функции диалекта для такого расчета. Другая возможность заключается в реализации и регистрации перехватчика (метод для переопределения onPrepareStatement
), если синтаксис со знаком плюс и минус является предпочтительным.
Когда решение не обязательно должно быть чисто на HQL и достаточно времени с хоста JVM, самое простое решение - это вычислить дату, прошедшую через 10 минут, и указать ее в качестве аргумента. Если время базы данных является предпочтительным, это можно сделать, запросив его в отдельном запросе, а затем уменьшив его на 10 минут.
Другие ответы на этот вопрос были правильными в отношении Hibernate 5 и более ранних версий, но, поскольку люди ссылаются на этот вопрос, я должен отметить, что они больше не верны в отношении Hibernate 6.
В H6 запрос можно записать на HQL так:
select id, name from Entity where date_creation + 10 minute < current_timestamp