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