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

GET接口返回指定JSON响应:部门员工多对多关联查询结果重映射方案

你当前返回的是多对多关联的中间表实体DepartmentEmployee,仅包含中间表的复合主键、任职起止时间字段,没有加载关联的Employee实体数据,且序列化结构不符合需求,按以下步骤修改即可:


方案说明:推荐使用DTO(数据传输对象)实现,实现实体与API响应结构解耦,避免污染持久层实体

步骤1:调整Repository查询逻辑,关联加载员工详情

原来的查询仅加载了中间表数据,需要补充关联抓取中间表绑定的员工实体,避免懒加载异常:

@Override
public Optional<Department> findByIdWithEmployees(String deptNo) {
    // 新增JOIN FETCH e.employee 抓取关联的员工数据
    TypedQuery<Department> query = this.entityManager.createQuery("SELECT d FROM Department d JOIN FETCH d.employees e JOIN FETCH e.employee emp WHERE d.deptNo = :deptNo AND e.toDate IS NULL", Department.class).setParameter("deptNo", deptNo);
    return Optional.ofNullable(query.getSingleResult());
}

步骤2:定义对应响应结构的DTO类

// 员工详情响应DTO
@Data // 可用Lombok简化,若无则手动加getter、setter、无参构造
public class EmployeeRespDTO {
    private Integer empNo;
    private LocalDate birthDate;
    private String firstName;
    private String lastName;
    private String gender;
    private LocalDate hireDate;
}

// 部门员工任职响应DTO
@Data
public class DeptEmployeeRespDTO {
    private LocalDate fromDate;
    private LocalDate toDate;
    private EmployeeRespDTO employee;
}

步骤3:修改Service层逻辑,完成实体到DTO的转换

@Override
public List<DeptEmployeeRespDTO> listAllEmployeesPerDepartment(String deptNo) {
    Department department = this.departmentRepository.findByIdWithEmployees(deptNo).orElseThrow(() -> new DepartmentNotFoundException(deptNo));
    // 手动转换,也可集成MapStruct等工具自动转换
    return department.getEmployees().stream().map(deptEmp -> {
        DeptEmployeeRespDTO resp = new DeptEmployeeRespDTO();
        resp.setFromDate(deptEmp.getFromDate());
        resp.setToDate(deptEmp.getToDate());
        // 转换员工信息,需确保DepartmentEmployee实体已配置Employee关联映射
        Employee emp = deptEmp.getEmployee();
        EmployeeRespDTO empResp = new EmployeeRespDTO();
        empResp.setEmpNo(emp.getEmpNo());
        empResp.setBirthDate(emp.getBirthDate());
        empResp.setFirstName(emp.getFirstName());
        empResp.setLastName(emp.getLastName());
        empResp.setGender(emp.getGender());
        empResp.setHireDate(emp.getHireDate());
        resp.setEmployee(empResp);
        return resp;
    }).toList();
}

步骤4:修改Controller层返回值类型

@GetMapping("/{deptNo}/employees")
public List<DeptEmployeeRespDTO> getEmployeesPerDepartment(@PathVariable String deptNo) {
    return this.employeeService.listAllEmployeesPerDepartment(deptNo);
}

临时调试方案:若不想新增DTO,可通过Jackson注解调整实体序列化规则

  1. 先完成上述步骤1的查询修改,确保员工实体已被加载
  2. 在DepartmentEmployee实体的复合主键id字段上加@JsonIgnore注解,避免序列化主键字段
  3. 确保DepartmentEmployee实体中关联Employee的字段没有加@JsonIgnore,即可直接返回符合要求的结构

该方案仅适合临时调试,生产环境推荐用DTO解耦


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 04:06:04