У меня есть следующие сущности:
Банк
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. Буду благодарен любой помощи.