Автор оригинала: Vlad Mihalcea.
Вступление
В этой статье мы рассмотрим, как лучше всего настроить интервал ожидания запроса с помощью JPA и гибернации.
Установка времени ожидания запроса позволяет отменить медленно выполняемые запросы, которые в противном случае оказали бы давление на ресурсы базы данных.
Тайм-аут запроса с JPA и гибернацией @vlad_mihalcea Узнайте больше: https://t.co/ijnTgcAKdF pic.twitter.com/D5hqTuvhiJ
“Явакс.настойчивость.запрос.тайм-аут” Подсказка по запросу JPA
Как я объяснил в этой статье , API сохранения Java определяет понятие подсказка запроса , которое, в отличие от того, что может предполагать его название, не имеет ничего общего с подсказками запроса базы данных. Подсказка запроса JPA-это опция настройки поставщика сохраняемости Java.
JPA обеспечивает поддержку установки интервала ожидания для данной сущности или SQL-запроса с помощью javax.persistence.запрос.тайм-аут
подсказка по запросу:
Listposts = entityManager .createQuery( "select p " + "from Post p " + "where lower(p.title) like lower(:titlePattern)", Post.class) .setParameter("titlePattern", "%Hibernate%") .setHint("javax.persistence.query.timeout", 50) .getResultList();
Значение тайм-аута определено в миллисекундах, поэтому приведенный выше запрос JPQL завершится через 50 миллисекунд, если только набор результатов не будет получен до порогового значения тайм-аута.
Подсказка запроса “org.hibernate.timeout” для перехода в спящий режим
Hibernate также предоставляет подсказку org.hibernate.timeout
запроса, которая, в отличие от ее аналога JPA, занимает интервал ожидания в секундах:
Listposts = entityManager .createQuery( "select p " + "from Post p " + "where lower(p.title) like lower(:titlePattern)", Post.class) .setParameter("titlePattern", "%Hibernate%") .setHint("org.hibernate.timeout", 1) .getResultList();
Свойство тайм-аута запроса Hibernate
Если вы развернете JPA javax.persistence.Запрос
в режим гибернации org.hibernate.запрос.Интерфейс запроса
, расширяющий спецификацию запроса JPA, позволяет получить доступ к методам расширения запросов Hibernate, которые позволяют задать комментарий на уровне SQL, подсказку или указать пороговое значение времени ожидания.
Listposts = entityManager .createQuery( "select p " + "from Post p " + "where lower(p.title) like lower(:titlePattern)", Post.class) .setParameter("titlePattern", "%Hibernate%") .unwrap(org.hibernate.query.Query.class) .setTimeout(1) .getResultList();
Точно так же, как это было в случае с подсказкой org.hibernate.timeout
запроса, метод setTimeout
использует интервал ожидания в секундах, поэтому приведенный выше запрос JPQL истечет через одну секунду, если запрос не завершится быстрее.
Время тестирования
Чтобы увидеть, как работает тайм-аут запроса, рассмотрим следующий пример:
Listresult = entityManager .createNativeQuery( "SELECT 1 " + "FROM pg_sleep(2) ", Tuple.class) .setHint( "javax.persistence.query.timeout", (int) TimeUnit.SECONDS.toMillis(1) ) .getResultList();
При выполнении запроса PostgreSQL выше база данных выдаст query_canceled
исключение:
SELECT 1 FROM pg_sleep(2) -- SQL Error: 0, SQLState: 57014 -- ERROR: canceling statement due to user request
Автоматическое применение интервала ожидания для гибернации запросов
Если вы хотите автоматически применять время ожидания запроса ко всем запросам в режиме гибернации, вам следует передать JPA javax.persistence.запрос.тайм-аут
подсказка запроса как свойство:
И затем вы выполняете следующий JPQL-запрос:
Listposts = entityManager .createQuery( "select p " + "from Post p " + "where function('1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(2) ) --',) is ''", Post.class) .getResultList();
Затем Hibernate выдаст исключение тайм-аута запроса, даже если мы явно не указали интервал тайм-аута в запросе JPQL:
SELECT p.id AS id1_0_, p.title AS title2_0_ FROM post p WHERE 1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(2) ) --()='' -- SQL Error: 0, SQLState: 57014 -- ERROR: canceling statement due to user request
Круто, правда?
Вывод
Установка интервала ожидания запроса очень полезна, так как в противном случае медленные выполняемые запросы будут удерживать соединение с базой данных, полученное в течение длительного периода времени, следовательно, оказывая давление на параллелизм и масштабируемость.