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的查询修改,确保员工实体已被加载
- 在
DepartmentEmployee实体的复合主键id字段上加@JsonIgnore注解,避免序列化主键字段 - 确保
DepartmentEmployee实体中关联Employee的字段没有加@JsonIgnore,即可直接返回符合要求的结构
该方案仅适合临时调试,生产环境推荐用DTO解耦
内容的提问来源于stack exchange,提问作者Taulant Fazliu
相关产品推荐
相关产品推荐

