Задать вопрос
@smetannicPum

Как подгрузить две коллекции связанных сущностей минимальным количеством sql запросов?

У меня есть следующие сущности:

Банк

public class Bank {

    @Id
    @Column(name = "bank_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private UUID id;

    @Column(name = "bank_name")
    private String bankName;

    @OneToMany(orphanRemoval = true, cascade = CascadeType.ALL,
            mappedBy = "bank", fetch = FetchType.LAZY)
    private List<CreditDetails> creditDetails = new ArrayList<>();

    @OneToMany(orphanRemoval = true, cascade = CascadeType.ALL,
            mappedBy = "bank", fetch = FetchType.LAZY)
    private List<Client> clients = new ArrayList<>();
}


Клиент:
public class Client {

    @Id
    @Column(name = "client_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private UUID id;

    @Column(name = "client_name")
    private String clientName;

    @Column(name = "client_surname")
    private String clientSurName;

    @Column(name = "client_full_name")
    private String clientFullName;

    @Column(name = "telephone_number")
    private Long telephoneNumber;

    @Column(name = "email")
    private String email;

    @Column(name = "passport_number")
    private Long passportNumber;

    @ManyToOne(
            cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinColumn(name = "bank_id")
    private Bank bank;

    @OneToMany(cascade = CascadeType.ALL,
            mappedBy = "client")
    private List<CreditOffer> creditOffers = new ArrayList<>();

}


Детали Кредитного Предложения:

public class CreditDetails {

    @Id
    @Column(name = "credit_details_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private UUID id;

    @Column(name = "credit_limit")
    private BigDecimal creditLimit;

    @Column(name = "credit_percent")
    private BigDecimal creditPercent;

    @ManyToOne(targetEntity = Bank.class, cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinColumn(name = "bank_id")
    private Bank bank;

    @OneToMany(cascade = CascadeType.ALL,
            mappedBy = "creditDetails")
    List<CreditOffer> creditOffers = new ArrayList<>();
}


Моя задача,подгрузить Клиентов и Кредитные предложения наименьшим количеством запросов,используя Spring Data.

Изначально я попробовал решить эту задачу с помощью графов,добавил над сущностью банка следующую конструкцию:

@NamedEntityGraph(name = "BankWithClientsAndDetails", attributeNodes = {
        @NamedAttributeNode(value = "creditDetails"),
        @NamedAttributeNode(value = "clients",subgraph = "ClientWithBank")
})


Однако при вызове метода получил MultyBagFetchException,нагуглил что это возникает из-за того что в запросе получается декартовое произведение. Далее я попытался решить проблему в лоб и написать sql запрос вручную,сделал тестовый метод следующего вида:

@Query(value = "SELECT * FROM banks \n" +
            "JOIN clients ON clients.bank_id = banks.bank_id  \n" +
            "JOIN credit_details ON credit_details.bank_id = banks.bank_id \n" +
            "WHERE banks.bank_id = :id",nativeQuery = true)
    Optional<Bank> findBankWithSubEntitiesById(@Param(value = "id") UUID id);


Количество запросов так и осталось огромным,так как у связанных сущностей есть еще связанные сущности,а у тех еще одни. На этом этапе у меня опустились руки и я пришел к вам просить помощи. Как бы вы решили эту ситуацию? Неужели в моем случае придется смириться с N + 1. Буду благодарен любой помощи.
  • Вопрос задан
  • 92 просмотра
Подписаться 1 Сложный 9 комментариев
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы