lak
lak

Reputation: 534

API Request to ManyToOne relation

I'm trying to build an API which has a ManyToOne relation. It's about an Employee and Department entity. This is what I have:

@Entity
@Table
public class Employee {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    private Long Id;
    private String name;
    @ManyToOne(fetch=FetchType.LAZY)
    private Department department;
    //SETTERS AND GETTERS, TWO CONSTRUCTORS 
}

Department class

 @Entity
@Table
public class Department {

    @Id
    @GeneratedValue
    private Long Id;
    private String name;
    //SETTERS AND GETTERS, TWO CONSTRUCTORS 
}

Employee Controller

@RestController
public class EmployeeController {

    @Autowired
    EmployeeService employeeService;

    @PostMapping("/employee")
    public Employee create (@RequestBody Employee employee){

          return employeeService.create(employee);
    }
}

Department Controller

 @RestController
 public class DepartmentController {

     @Autowired
     private DepartmentService departmentService;

     @PostMapping("/departments")
     public Department create(@RequestBody Department department) {
       return departmentService.create(department);
   }
}

I need to add an Department and then add and employee that belongs to that department.

This is the POST request to Department and it works.

{
    "id": 2,
    "name": "Depto"             
 }

I need to add that department to an employee

 {
     "id": 2,
     "name": "Employee",
     "department": 2
 }

This is the error that I got:

 .HttpMessageNotReadableException: Could not read document: Cannot construct instance of 'mypackage.Department' (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (2)

Upvotes: 0

Views: 250

Answers (1)

Jason
Jason

Reputation: 11822

The department field in the Employee class is an instance of Department, not an integer. So the JSON you're POSTing is wrong. In fact, it's bad architectural practise to use the same class for persisting in the DB as what you send over REST calls.

If you separate them (make the REST object a DTO), then you can receive the id (2), look up the department with id 2 and then put that in your new Employee object and save it to the database.

Edit: You could create an EmployeeDTO class:

public class EmployeeDTO {
    private Long id;
    private String name;
    private Long departmentId;

    ...  // getters
}

And your controller might have an endpoint something like this:

@PostMapping("/employee")
public Employee create (@RequestBody EmployeeDTO employeeDTO){

    Department department = departmentService.get(employeeDTO.getDepartmentId());

    Employee employee = new Employee();
    employee.setId(employeeDTO.getId());
    employee.setName(employeeDTO.getName());
    employee.setDepartment(department);

    return employeeService.create(employee);
}

Upvotes: 2

Related Questions