JPQL执行JOIN操作时能否避免产生多条SQL查询?
JPA N+1查询问题解决方案
你遇到的是典型的JPA关联查询N+1问题,默认规则下查询主实体时,关联对象默认使用懒加载策略,只有在代码中访问关联对象属性时才会触发单独的查询,最终产生1条主查询+N条关联查询的结果。可通过以下几种方式解决:
方案1:修改JPQL使用fetch join(最推荐,针对性最强)
直接在原JPQL中对关联对象使用fetch关键字,指定查询时同步抓取关联数据,仅执行1条SQL完成所有数据加载。
修改后的查询代码如下:
@Query("select Q from Order Q join fetch customer C on Q.customer_id=C.id where Q.created_date >= '2021-11-01'")
该方案仅对当前查询生效,不会影响其他业务逻辑的关联加载策略,适合单业务场景的优化。
方案2:使用@EntityGraph注解
在Repository的查询方法上添加@EntityGraph注解,显式指定需要一起加载的关联字段,效果和fetch join一致:
@EntityGraph(attributePaths = {"customer"}) @Query("select Q from Order Q where Q.created_date >= '2021-11-01'") List<Order> findMonthOrders();
方案3:调整关联字段的加载策略
如果该关联在所有涉及Order查询的场景下都需要同步加载,可以直接修改Order实体中customer关联注解的fetch属性:
@ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "customer_id") private Customer customer;
注意:该配置全局生效,若其他查询不需要关联customer数据会产生性能浪费,非必要不推荐使用。
方案4:配置Hibernate批量抓取参数
如果不想修改原有查询逻辑,也可以通过全局配置降低N+1的性能损耗,在application.properties中添加如下配置:
# 配置批量抓取大小,可根据业务实际情况调整数值 spring.jpa.properties.hibernate.default_batch_fetch_size=100
配置后关联查询会按设定的批量大小合并查询,80条订单的场景下仅需执行2条SQL(1条订单查询+1条批量客户查询),性能提升明显。
内容的提问来源于stack exchange,提问作者Michael NGV
相关产品推荐
相关产品推荐

