JPA одиночный запрос для извлечения вложенной коллекции - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть приложение Java 11 Spring Boot, и я использую JPA с Hibernate.

public class Test {
   (...)

    @OneToMany(cascade = CascadeType.REMOVE)
    @JoinColumn(name = "test_id", nullable = false)
    private List<Question> availableQuestions;

   (...)
public class Question {
    (...)
    @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.REMOVE}, orphanRemoval = true)
    @JoinColumn(name = "question_id", nullable = false)
    private List<Answer> availableAnswers;
    (...)
public class Answer {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="answer_id_seq")
    @SequenceGenerator(name = "answer_id_seq", allocationSize = 1)
    @Column(name = "answer_id")
    private Long id;
    @Column(name = "text", length = 500)
    private String text;
    @Column(name = "is_correct")
    private boolean isCorrect;

Теперь в моем коде мне нужно получить тестируйте и перебирайте его доступные вопросы и для каждого вопроса перебирайте его доступные ответы. Это создает неприятную проблему n + 1, поскольку для каждого вопроса делается отдельный вызов для получения ответов.

Вопрос: Что можно сделать, чтобы получить тест с вопросами и ответами, полученными в одном query?

Я пытался использовать fetchType.EAGER в доступных ответах, но это все равно приводило к n запросам, чтобы получить ответы на все вопросы (это было сделано раньше, прежде чем был вызван метод getter). Я также попробовал пользовательский запрос jpql с выборкой соединения, и я также попробовал граф сущностей. Получил MultipleBagFetchException из спящего режима на обоих.

1 Ответ

0 голосов
/ 28 апреля 2020

У вас есть 2 способа избежать n + 1 проблем.

Отношение загрузки в JPQL FETCH JOIN или с использованием EntityGraph.

С извлечением соединения ->

Select distinct t from Test t LEFT JOIN FETCH t.availableQuestions q LEFT JOIN FETCH q.availableAnswers a

Относительно MultipleBagFetchException чтобы избежать «повторяющейся» проблемы, вы можете переключить тип коллекции с List type на Set.

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