Текст JPQL запроса может включать макросы, которые обрабатываются перед выполнением и превращаются в исполняемый JPQL, дополнительно модифицируя набор параметров.
Макросы, определенные в платформе, решают следующие задачи:
-
Позволяют обойти принципиальную невозможность средствами JPQL выразить условие зависимости значения поля от текущего момента времени (не работает арифметика типа current_date-1)
-
Позволяют сравнивать с датой поля типа Timestamp (содержащие дату+время)
Рассмотрим их подробно:
- @between
-
Имеет вид
@between(field_name, moment1, moment2, time_unit)
, где-
field_name
- имя атрибута для сравнения -
moment1
,moment2
- моменты времени, в которые должно попасть значение атрибутаfield_name
. Каждый из моментов должен быть определен выражением с участием переменнойnow
, к которой может быть прибавлено или отнято целое число -
time_unit
- определяет единицу измерения времени, которое прибавляется или вычитается изnow
в выражениях моментов, а также точность округления моментов. Может быть следующим:year
,month
,day
,hour
,minute
,second
. При включенном базовом проекте workflow можно также использовать единицы рабочего времени:workday
,workhour
, workminute.
Макрос преобразуется в следующее выражение JPQL:
field_name >= :moment1 and field_name < :moment2
Пример 1. Покупатель создан сегодня:
select c from sales$Customer where @between(c.createTs, now, now+1, day)
Пример 2. Покупатель создан в течение последних 10 минут:
select c from sales$Customer where @between(c.createTs, now-10, now, minute)
Пример 3. Документы, датированные последними 5 рабочими днями (для проектов, включающих workflow):
select d from sales$Doc where @between(d.createTs, now-5, now, workday)
-
- @today
-
Имеет вид
@today(field_name)
и обеспечивает формирование условия попадания значения атрибута в текущий день. По сути это частный случай макроса@between
.Пример. Пользователь создан сегодня:
select d from sales$Doc where @today(d.createTs)
- @dateEquals
-
Имеет вид
@dateEquals(field_name, parameter)
и позволяет сформировать условие попадания значения поляfield_name
типаTimestamp
в дату, задаваемую параметромparameter
.Пример:
select d from sales$Doc where @dateEquals(d.createTs, :param)
- @dateBefore
-
Имеет вид
@dateBefore(field_name, parameter
) и позволяет сформировать условие, что дата значения поляfield_name
типаTimestamp
меньше даты, задаваемой параметромparameter
.Пример:
select d from sales$Doc where @dateBefore(d.createTs, :param)
- @dateAfter
-
Имеет вид
@dateAfter(field_name, parameter
) и позволяет сформировать условие, что дата значения поляfield_name
типаTimestamp
больше или равна дате, задаваемой параметромparameter
.Пример:
select d from sales$Doc where @dateAfter(d.createTs, :param)
- @enum
-
Позволяет использовать полное имя константы enum вместо ее идентификатора в БД. Это упрощает поиск использований enum в коде приложения.
Пример:
select r from sec$Role where r.type = @enum(com.haulmont.cuba.security.entity.RoleType.SUPER) order by r.name
Список макросов может быть расширен в прикладном проекте. Для создания нового макроса необходимо определить бин, реализующий
интерфейс QueryMacroHandler
, и задать ему @Scope("prototype")
. Механизм выполнения JPQL запросов создает все доступные бины типа QueryMacroHandler
, и по очереди передает им текст запроса с набором параметров. Очередность вызова обработчиков не определена.