You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot Specification关联列fetch方法对性能的影响分析

问题背景

假设有一个Spring Boot项目,包含Campus、Employee、Department三个实体,关联关系如下:

  • Campus包含大量Employee
  • 每个Employee仅属于一个Department(Department为核心主数据实体)

实体定义代码如下:

public class Campus {
    @Id
    private String campusNo;

    @JsonManagedReference
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "employee")
    private List<Employee>employeeList = new ArrayList<>();
}

public class Employee {
    @Id
    private String employeeCode;

    @JsonBackReference
    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "campusNo", nullable = false)
    private Campus campus;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(referencedColumnName = "departMentNo")
    private Department department;
}

public class Department {
    @Id
    private String departMentNo;
}

现在需要使用Specification构建可配置报表,对比以下两个fetch语句(标记为Option 1和Option 2)哪种能减少SQL查询语句数量,并分析各自的优缺点:

public class CampusSpecification implements Specification<Campus> {
    private SearchCriteria searchCriteria;

    @Override
    public Predicate toPredicate(Root<Campus> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
        root.fetch("employeeList").fetch("department"); // Option 1
        root.fetch("employeeList"); // Option 2
        return criteriaBuilder.in(root.get("employeeList").get("department").get("departMentNo")).value(searchCriteria.getValue());
    }
}
分析与结论

结论:Option 1能减少SQL查询语句数量

Option 1(root.fetch("employeeList").fetch("department"))

  • 优势:
    • 采用关联抓取方式,一次性通过JOIN语句关联Campus、Employee、Department三张表,全程仅执行1条SQL即可加载所有需要的实体数据,彻底避免N+1查询问题
    • 后续访问Campus的员工列表、员工对应的部门属性时,不会触发额外的懒加载查询,直接使用已加载的内存数据
  • 劣势:
    • 若Campus关联的Employee数量极大,单条SQL返回的结果集会非常庞大,可能导致内存占用过高,甚至拖慢数据库查询性能
    • 多表关联的SQL复杂度较高,数据库解析和执行的开销会比单表/两表查询更大

Option 2(root.fetch("employeeList"))

  • 优势:
    • 仅抓取Campus和Employee的数据,SQL结果集相对较小,在员工数量较多时,内存压力比Option 1更低
    • 仅涉及两张表关联,SQL结构简单,数据库执行效率相对更高
  • 劣势:
    • 当访问每个Employee的department属性时,会触发N+1查询(1条查询校区和员工的SQL,加上N条查询部门的SQL,N为员工数量),导致SQL查询数量暴增,整体性能大幅下降
    • 大量额外查询会占用更多数据库连接,高并发场景下可能耗尽连接池,引发服务异常

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 11:01:09