Использование Spring Query Methods JPA для эффективного запроса БД без нескольких операторов SELECT - PullRequest
0 голосов
/ 18 апреля 2019

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

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

Я искал FetchTypes и язык Spring QueryData, а также DTO Projection, но думаю, что может быть более простой способ. Преимущество, которое я воспринимал как должное, заключается в явном выполнении JOIN, если я добавлю новое поле, тогда мне придется постоянно обновлять свой запрос, а если 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 Ответ

0 голосов
/ 18 апреля 2019

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

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

(Необязательно), должна ли коллекция загружаться лениво или загружаться с нетерпением.Стратегия EAGER - это требование времени выполнения провайдера постоянства, что элементы коллекции должны извлекаться с нетерпением.Стратегия LAZY - это подсказка для среды выполнения персистентного провайдера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...