3.4.4.4. Выполнение JPQL запросов
В данном разделе описывается интерфейс Query
, предназначенный для выполнения JPQL запросов на уровне ORM. Ссылку на Query
можно получить у текущего экземпляра EntityManager
вызовом метода createQuery()
. Если запрос предполагается использовать для извлечения сущностей, рекомендуется вызывать createQuery()
с передачей типа результата, что приведет к созданию TypedQuery
.
Методы Query
в основном соответствуют методам стандартного интерфейса JPA javax.persistence.Query
. Рассмотрим отличия.
-
setView()
,addView()
- устанавливают представление, используемое при загрузке данных. -
getDelegate()
- возвращает экземплярjavax.persistence.Query
, предоставляемый реализацией ORM.
Если для Query
установлено представление, то по умолчанию Query
имеет FlushModeType.AUTO
, что влияет на случай, когда в текущем персистентном контексте содержатся измененные экземпляры сущностей: эти экземпляры будут сохранены в БД перед выполнением запроса. Другими словами, ORM сначала синхронизирует состояние сущностей в персистентном контексте и в БД, а уже потом выполняет запрос. Этим гарантируется, что в результаты запроса попадут все соответствующие экземпляры, даже если они еще не были сохранены в базе данных явно. Обратной стороной этого является неявный flush, т.е. выполнение команд SQL update для всех измененных в данном контексте сущностей, что может повлиять на производительность.
Если же Query
выполняется без представления, то по умолчанию Query
имеет FlushModeType.COMMIT
, что означает, что неявный flush вызван не будет, и запрос не будет учитывать содержимое текущего персистентного контекста.
В большинстве случаев игнорирование текущего персистентного контекста допустимо, и является предпочтительным поведением, так как не вызывает дополнительных команд SQL. Однако, при использовании представлений существует следующая проблема: если в персистентном контексте есть измененный экземпляр сущности, и выполняется запрос с представлением и FlushModeType.COMMIT
, загружающий этот же экземпляр, то изменения будут потеряны. Поэтому по умолчанию мы используем FlushModeType.AUTO
для запросов с представлением.
Вы также можете явно установить flush mode с помощью метода setFlushMode()
интерфейса Query
, чтобы переопределить режим по умолчанию.
- Using DELETE FROM with soft-deleted entities
-
Если в проекте используется мягкое удаление, то при выполнении JPQL-запроса
DELETE FROM
для сущности, удалённой через мягкое удаление, будет выброшено исключение. Дело в том, что такой запрос, по сути, будет трансформирован в запрос SQL для удаления всех сущностей, не помеченных для удаления. По умолчанию такое неочевидное поведение запрещено, но его можно разрешить с помощью свойства приложения cuba.enableDeleteStatementInSoftDeleteMode.
- Query Hints
-
Метод
Query.setHint()
позволяет добавить некоторые подсказки (hints) в генерируемые команды SQL. Подсказки обычно используются для указания того, как запрос должен использовать индексы, или другую специфику СУБД. Фреймворк определяет следующие константы, которые можно использовать в качестве имен задаваемых подсказок:-
QueryHints.SQL_HINT
- значение подсказки будет добавлено после сгенерированной команды SQL. Указывайте полный текст подсказки, включая разделители комментариев, если они требуются. -
QueryHints.MSSQL_RECOMPILE_HINT
- будет добавлено выражениеOPTION(RECOMPILE)
для СУБД MS SQL Server. Значение подсказки при этом игнорируется.
При работе с DataManager подсказки в запрос можно передать, используя метод
LoadContext.setHint()
. -