I have a many-to-many relationship between Department and Employee
I have already done a mapping for the GET endpoint which returns a list of departments that contain Employees, this is the request: http://localhost:8080/api/departments/1/employees
, and this is the response I get:
[
{
"id": {
"deptNo": "1 ",
"empNo": 2
},
"fromDate": "2021-11-22",
"toDate": null
}
]
This is the code that gets the job done:
Department Repository Imp
@Override
public Optional<Department> findByIdWithEmployees(String deptNo) {
TypedQuery<Department> query = this.entityManager.createQuery("SELECT d FROM Department d JOIN FETCH d.employees e WHERE d.deptNo = :deptNo AND e.toDate IS NULL", Department.class).setParameter("deptNo", deptNo);
return Optional.ofNullable(query.getSingleResult());
}
Employee Service Impl
@Override
public List<DepartmentEmployee> listAllEmployeesPerDepartment(String deptNo) {
Department department = this.departmentRepository.findByIdWithEmployees(deptNo).orElseThrow(() -> new DepartmentNotFoundException(deptNo));
return department.getEmployees();
}
Department Controller
@GetMapping("/{deptNo}/employees")
public List<DepartmentEmployee> getEmployeesPerDepartment(@PathVariable String deptNo) {
return this.employeeService.listAllEmployeesPerDepartment(deptNo);
}
Now what I need is to re-map this so I get a different response. This is the response I need to receive when I run a GET request:
[
{
"fromDate":"2021-11-22",
"toDate":null,
"employee":{
"empNo":2,
"birthDate":"1997-05-10",
"firstName":"Taulant",
"lastName":"Fazliu",
"gender":"M",
"hireDate":"2020-01-01"
}
}
]
How to achieve this?
CodePudding user response:
If the response you want to give has a different structure from your model (the first diagram you showed), you need to implement the DTO pattern.
DTO: Data Transfer Object. It just means, in words of Samuel L. Jackson "hey you! Do you want to show your shit in a different way? Create a new mother fucker object that represents the new shit, and damn transform it!"
So, create a new object called DepartmentEmployeeDTO
with the structure you want to show, and use a Builder
pattern to transform from one to another. And of course make getEmployeesPerDepartment
return List<DepartmentEmployeeDTO>
. That method will end up as something like this:
@GetMapping("/{deptNo}/employees")
public List<DepartmentEmployeeDTO> getEmployeesPerDepartment(@PathVariable String deptNo) {
return this.employeeService.listAllEmployeesPerDepartment(deptNo)
.stream()
.map(e -> new DepartmentEmployeeDTOBuilder(e).build())
.collect(Collectors.toList());
}
That provided you build you Builder
with one constructor with the original DepartmentEmployee
as the only parameter.