Использование методов Spring Query JPA для эффективного запроса к БД без нескольких операторов SELECT

#spring #hibernate #spring-boot #jpa #spring-data-jpa

#spring #гибернация #spring-boot #jpa #spring-data-jpa

Вопрос:

У меня есть объект, который имеет простые строковые столбцы, а также множество ElementCollections (список и карта). Я заметил, просматривая свои журналы postgres, что PostGres при запросе этого объекта последовательно выполняет несколько запросов SELECT, чтобы получить все ElementCollections.

Для повышения эффективности я бы предположил, что выполнение одного запроса SELECT с некоторыми внутренними объединениями может быть лучше, чтобы избежать всех отдельных запросов SELECT. Есть ли способ сделать это без написания очень подробного запроса select вручную со всеми ВНУТРЕННИМИ объединениями?

Я изучал FetchTypes и язык Spring QueryData, а также проекцию DTO, но я полагаю, что может быть более простой способ. Преимущество, которое я считал само собой разумеющимся, заключается в явном выполнении соединений, если я добавлю новое поле, тогда мне придется постоянно обновлять свой запрос, и если Spring генерирует запросы для меня, тогда мне не нужно будет ничего делать.

 // Person.java

@Entity
public Person {

    @Id
    long personId;

    @Column
    String firstName;

    @Column
    String lastName;

    @ElementCollections
    Set<String> someField;

    @ElementCollections
    Map<String, String> otherField;

    @ElementCollections
    Set<String> anotherField;

    @ElementCollections
    Map<String, String> yetAnotherField;
}
 

То, что происходит прямо сейчас, это

 SELECT firstName, lastName FROM Person WHERE personId=$1
SELECT someField FROM Person_SomeField WHERE someField.personId=$1
SELECT otherField.key otherField.value FROM Person_OtherField WHERE otherField.personId=$1
 

И это продолжается для всех таблиц ElementCollections, что приводит к большому количеству запросов.

Ответ №1:

Измените аннотацию на @ElementCollection(fetch = FetchType.EAGER) .

Похоже, что эти поля загружаются лениво (Hibernate ожидает, пока к ним не будет получен доступ для их загрузки), что приводит к N 1 запросам, которые вы видите. LAZY загрузка — это поведение по умолчанию для этого типа элементов, что имеет смысл, поскольку загрузка его обходится недешево. Однако, если вы всегда хотите, чтобы эти элементы были загружены, установка его EAGER может иметь смысл. Установка выборки в EAGER значение заставит Hibernate загружать их вместе с самим объектом. Это документация для fetch опции на @ElementCollection :

(Необязательно) Должна ли коллекция загружаться лениво или должна быть извлечена с нетерпением. Стратегия ожидания — это требование среды выполнения поставщика сохраняемости, согласно которому элементы коллекции должны быть извлечены с готовностью. ОТЛОЖЕННАЯ стратегия — это подсказка для среды выполнения поставщика сохраняемости.