`@PostMapping`与多个`RequestBody`

huangapple go评论83阅读模式
英文:

@PostMapping with multiple RequestBody

问题

以下是翻译好的部分:

我对Java Spring非常新手,有一个小问题。

我想在请求体(在Postman中)中发送employee_id(来自employees实体)到assignment实体。目前它是可以工作的,因为我将employee_id作为PathVariable发送,而且我正在使用ResponseBody发送assignment数据。

@PostMapping("/add/{employee_id}")
public void addEmployee(@PathVariable(value = "employee_id", required = false) Long employee_id, 
          @RequestBody Assignment a) {

    Employee employeeById = employeeRepository.findById(employee_id)
            .orElseThrow(() -> new RuntimeException("Employee not found"));

    a.setEmployee(employeeById);
    assignmentRepository.addAssignment(a);
}

它可以与URL localhost:8080/add/35 一起工作。35是employee_id,分配数据可以在Postman的请求体中发送。我想要做的是,也将employee_id放在请求体中(这样URL应该只是/add),但我无法让它工作。

就像这样:

{
   "employee_id": 35,
   "title": "abc"
}

编辑后:

Assignment.java

public class Assignment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @OneToOne(optional = false)
    @JoinColumn(name = "employee_id", nullable = false)
    private Employee employee;

    @Size(min = 3, max = 50)
    private String assignment_title;

    public Assignment() {
    }

    public Assignment(String assignment_title) {
        super();
        this.assignment_title = assignment_title;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getAssignment_title() {
        return assignment_title;
    }

    public void setAssignment_title(String assignment_title) {
        this.assignment_title = assignment_title;
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }
}

AssignmentService.java

public void addAssignment(Assignment e) {
    assignmentRepository.save(e);
}

AssignmentRepository.java

public interface AssignmentRepository extends CrudRepository<Assignment, Integer> {
    
}

Employee.java

public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    @OneToOne(optional = false)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;

    @Size(min=3, max = 100)
    private String title;

    @Size(min=3, max = 50)
    private String staff;

    private Long degree;

    public Employee() {}
 
    public Employee(String title, String staff, Long degree) {
        super();
        this.title = title;
        this.staff = staff;
        this.degree = degree;
    }
    
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    public String getStaff() {
        return staff;
    }
 
    public void setStaff(String staff) {
        this.staff = staff;
    }

    public Long getDegree() {
        return degree;
    }
 
    public void setDegree(Long degree) {
        this.degree = degree;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

EmployeeRepository.java

public interface EmployeeRepository extends CrudRepository<Employee, Integer> {
    Optional<Employee> findById(Long id);
}

提前感谢您的帮助!

英文:

I'm very new to Java Spring and have a little Problem.

I wan't to send the employee_id (from employees entity) to assignment entity in the body part (in Postman). Currently it's working, because I'm sending the employee_id as a PathVariable and I'm sending the assignment data with ResponseBody.

@PostMapping(&quot;/add/{employee_id}&quot;)
public void addEmployee(@PathVariable(value = &quot;employee_id&quot;, required = false) Long employee_id, 
@RequestBody Assignment a) {
Employee employeeById = employeeRepository.findById(employee_id)
.orElseThrow(() -&gt; new RuntimeException(&quot;Employee not found&quot;));
a.setEmployee(employeeById);
assignmentRepository.addAssignment(a);
}

It is working with the url localhost:8080/add/35. 35 is the employee_id and the assignment data can be send in the Body (of Postman). What I want to do is, to send the employee_id in the body too (so the url should only be /add), but I could not get it to work.

Like that:

{
&quot;employee_id&quot;: 35,
&quot;title&quot;: &quot;abc&quot;
}

Edited:

Assignment.java

public class Assignment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@OneToOne(optional = false)
@JoinColumn(name = &quot;employee_id&quot;, nullable = false)
private Employee employee;
@Size(min = 3, max = 50)
private String assignment_title;
public Assignment() {
}
public Assignment(String assignment_title) {
super();
this.assignment_title = assignment_title;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAssignment_title() {
return assignment_title;
}
public void setAssignment_title(String assignment_title) {
this.assignment_title = assignment_title;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
}

AssignmentService.java

   public void addAssignment(Assignment e) {
AssignmentRepository.save(e);
}

AssignmentRepository.java

public interface AssignmentRepository extends CrudRepository&lt;Assignment, Integer&gt;{
}

Employee.java

public class Employee{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@OneToOne(optional = false)
@JoinColumn(name = &quot;user_id&quot;, nullable = false)
private User user;
@Size(min=3, max = 100)
private String title;
@Size(min=3, max = 50)
private String staff;
private Long degree;
public Employee() {}
public Employee( String title, String staff, Long degree) {
super();
this.title = title;
this.staff = staff;
this.degree = degree;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getStaff() {
return staff;
}
public void setStaff(String staff) {
this.staff = staff;
}
public Long getDegree() {
return degree;
}
public void setDegree(Long degree) {
this.degree = degree;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}

EmployeeRepository.java

public interface EmployeeRepository extends CrudRepository&lt;Employee, Integer&gt;{
Optional&lt;Employee&gt; findById(Long id);
}

Thanks for your help in advance!

答案1

得分: 3

你需要确保你的身体类型Assignment具有以下属性,如下所示:

public class Assignment {
    public Long employee_id;
    // 省略其他
}

并且在你的方法中获取它,如下所示:

@PostMapping("/add")
public void addEmployee(@PathVariable(value = "employee_id", required = false) Long employee_id, @RequestBody Assignment a) {
    Long employee_id = a.employee_id;
    Employee employeeById = employeeRepository.findById(employee_id)
        .orElseThrow(() -> new RuntimeException("Employee not found"));
    a.setEmployee(employeeById);
    assignmentRepository.addAssignment(a);
}

但是这样的实现不符合HTTP标准。请考虑实际情况,几乎符合这些标准,你应该像这样重命名你的API:POST URL/v1/employees/{employee_id}。这个博客解释了这些标准。

根据提供的规范进行编辑:

@PostMapping(values = {"/v1/employees", "/v1/employees/{employee_id}"})
public void addEmployee(@PathVariable(value = "employee_id", required = false) Long employee_id, @RequestBody Assignment a) {
    Long yourId = employee_id != null ? employee_id : a.employee_id;
    if (yourId == null) {
        throw new RuntimeException("No id given"); // 不太干净,但由OP实现
    } else {
        Employee employeeById = employeeRepository.findById(yourId)
            .orElseThrow(() -> new RuntimeException("Employee not found"));
        a.setEmployee(employeeById);
        assignmentRepository.addAssignment(a);
    }
}

由于路径变量是可选的,你首先尝试从URL中获取它,然后从你的请求体对象中获取它。

第二次编辑:一个Assignment可能没有Employee_id
第一种情况:你接受Assignment可能没有Employee
只需更改从AssignmentEmployee的关系:

    @OneToOne(optional = true)
    @JoinColumn(name = "employee_id", nullable = true)
    private Employee employee;

第二种情况:你想先创建一个新的Employee,然后将其绑定到你的Assignment,因为一个Assignment应该始终有一个Employee

@PostMapping(values = {"/v1/employees", "/v1/employees/{employee_id}"})
public void addEmployee(@PathVariable(value = "employee_id", required = false) Long employee_id, @RequestBody Assignment a) {
    Long yourId = employee_id != null ? employee_id : a.employee_id;
    Employee employeeById = yourId != null ?
        employeeRepository.findById(yourId).orElseThrow(() -> new RuntimeException("Employee not found"))
        : new Employee("title","staff",2L);
    a.setEmployee(employeeById);
    assignmentRepository.addAssignment(a);
}
英文:

You need to ensure your body type Assignment has such property like

public class Assignment {
    public Long employee_id;
    // ommitted
}

And get it in your method like

@PostMapping(&quot;/add&quot;)
public void addEmployee(@PathVariable(value = &quot;employee_id&quot;, required = false) Long employee_id, @RequestBody Assignment a) {
    Long employee_id = a.employee_id;
    Employee employeeById = employeeRepository.findById(employee_id)
        .orElseThrow(() -&gt; new RuntimeException(&quot;Employee not found&quot;));
    a.setEmployee(employeeById);
    assignmentRepository.addAssignment(a);
}

But such implementation does not respect HTTP standards.
Please consider that your actual implementation almost respect those standards and you should rename your API this way : POST URL/v1/employees/{employee_id}
This blog explains those standards

EDIT with provided specifications:

@PostMapping(values = {&quot;/v1/employees&quot;, &quot;/v1/employees/{employee_id}&quot;})
public void addEmployee(@PathVariable(value = &quot;employee_id&quot;, required = false) Long employee_id, @RequestBody Assignment a) {
    Long yourId = employee_id != null ? employee_id : a.employee_id;
    if (yourId == null) {
        throw new RuntimeException(&quot;No id given&quot;); // Not clean either but implemented by OP
    } else {
        Employee employeeById = employeeRepository.findById(yourId)
            .orElseThrow(() -&gt; new RuntimeException(&quot;Employee not found&quot;));
        a.setEmployee(employeeById);
        assignmentRepository.addAssignment(a);
    }
}

As the pathvariable is optionnal you try to get it first from url and then from your body object.

EDIT 2 : An Assignment might be created with no Employee_id
First case : You accept that an Assignment might have no Employee.
Simply change your relation from Assignment to Employee :

    @OneToOne(optional = true)
    @JoinColumn(name = &quot;employee_id&quot;, nullable = true)
    private Employee employee;

Second case : You want to create a new Employee first and then bind it to your assignement as an Assignment should always have an Employee

@PostMapping(values = {&quot;/v1/employees&quot;, &quot;/v1/employees/{employee_id}&quot;})
public void addEmployee(@PathVariable(value = &quot;employee_id&quot;, required = false) Long employee_id, @RequestBody Assignment a) {
    Long yourId = employee_id != null ? employee_id : a.employee_id;
    Employee employeeById = yourId != null ?
        employeeRepository.findById(yourId).orElseThrow(() -&gt; new RuntimeException(&quot;Employee not found&quot;))
        : new Employee(&quot;title&quot;,&quot;staff&quot;,2L);
    a.setEmployee(employeeById);
    assignmentRepository.addAssignment(a);
}

huangapple
  • 本文由 发表于 2020年9月15日 23:36:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63905270.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定