[Перевод] Катастрофа с Hibernate 6.5 при обновлении на Spring Boot 3.0.0

Обновившись до Spring Boot 3.0.0 (конкретно до Hibernate 6.5), мы столкнулись со 100% загрузкой процессора на БД из-за небольшого изменения в SQL коде, сгенерированного Hibernate после преобразования JPQL в SQL.

Image

100% потребление CPU

Посмотрите на следующий JPQL-запрос и обратите внимание на различия в генерации SQL для Hibernate 6.4 и Hibernate 6.5 при передаче пустого списка в качестве параметра.

interface ArticleRepository extends CrudRepository {  
  @Query("from Article where publisherId in :ids")
  List
findByPublisherId(List ids); } var articles = articleRepository.findByPublisherId(List.of());

Hibernate 6.4.X:

select a1_0.id, a1_0.publisher_id, a1_0.title
from article a1_0
where 1=0

Hibernate 6.5.X:

select a1_0.id, a1_0.publisher_id, a1_0.title
from article a1_0
where (1 = case when a1_0.publisher_id is not null then 0 end)

Может показаться, что разница незначительная, однако в PostgreSQL первый запрос выполняется практически мгновенно, а второй приводит к полному сканированию таблицы (full table scan).

Стоит отметить, что при использовании derived-query вместо @Query с JPQL запрос будет отличаться:

interface ArticleRepository extends CrudRepository {
List
findByPublisherId(List ids); } var articles = articleRepository.findByPublisherId(List.of());
select a1_0.id, a1_0.publisher_id, a1_0.title
from article a1_0
where a1_0.publisher_id in (?)

Команда Hibernate уже поправила этот баг: https://github.com/hibernate/hibernate-orm/pull/8528

Осталось дождаться включения этого фикса в модуль Spring Data JPA.

Присоединяйтесь к русскоязычному сообществу разработчиков на Spring Boot в телеграм — Spring АйО, чтобы быть в курсе последних новостей из мира разработки на Spring Boot и всего, что с ним связано.

Ждем всех,  присоединяйтесь!

© Habrahabr.ru