我有实体:
银行:
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以最少的请求加载Clients和Credit Details。
我试图用图来解决这个问题,我在bank实体上面添加了以下结构:
@NamedEntityGraph(name = "BankWithClientsAndDetails", attributeNodes = {
@NamedAttributeNode(value = "creditDetails"),
@NamedAttributeNode(value = "clients",subgraph = "ClientWithBank")
})
然而,当调用该方法时,我收到了一个MultyBagFetchException,在Google上搜索到这是由于在请求中获得了笛卡尔积。接下来,我试图通过手动编写一个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吗?我会感激任何帮助
1条答案
按热度按时间i7uaboj41#
在查询中只使用JOIN只会缩小结果范围,例如,它不会加载没有任何客户和信用详细信息的银行。
您可以使用JOIN FETCH jpql关键字告诉Hibernate急切地加载这些关联中的每一个。
请记住,这是一个jpql查询,因此您必须删除
nativeQuery = true
参数。另外,请注意,默认情况下,join是内部连接而不是外部连接-这意味着此查询也不会返回没有客户或信用详细信息的银行。您可以使用LEFT JOIN FETCH
更改此设置,但这会降低性能,因此请选择最适合您的用例的策略。Further reading