【发布时间】:2021-08-17 14:27:19
【问题描述】:
我尝试使用 Spring Rest Tutorial 学习 Spring 的基础知识,但有一件事对我来说真的很有趣。
实体类:
@Entity
class Employee {
private @Id @GeneratedValue Long id;
private String name;
private String role;
Employee() {}
Employee(String name, String role) {
this.name = name;
this.role = role;
}
public Long getId() {
return this.id;
}
public String getName() {
return this.name;
}
public String getRole() {
return this.role;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setRole(String role) {
this.role = role;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Employee))
return false;
Employee employee = (Employee) o;
return Objects.equals(this.id, employee.id) && Objects.equals(this.name, employee.name)
&& Objects.equals(this.role, employee.role);
}
@Override
public int hashCode() {
return Objects.hash(this.id, this.name, this.role);
}
@Override
public String toString() {
return "Employee{" + "id=" + this.id + ", name='" + this.name + '\'' + ", role='" + this.role + '\'' + '}';
}
}
我认为 EmployeeController 中的 replaceEmployee 方法有问题 - 有一段代码:
@PutMapping("/employees/{id}")
Employee replaceEmployee(@RequestBody Employee newEmployee, @PathVariable Long id) {
return repository.findById(id)
.map(employee -> {
employee.setName(newEmployee.getName());
employee.setRole(newEmployee.getRole());
return repository.save(employee);
})
.orElseGet(() -> {
newEmployee.setId(id);
return repository.save(newEmployee);
});
}
Snippet 建议如果没有 Employee 和 id,则使用请求路径中的 id 创建一个新员工。我已经对其进行了测试,似乎确实创建了 Employee ,但自动递增了id。
修改代码:
@PutMapping("/employees/{id}")
Employee replaceEmployee(@RequestBody Employee newEmployee, @PathVariable Long id) {
return repository.findById(id)
.map(employee -> {
employee.setName(newEmployee.getName());
employee.setRole(newEmployee.getRole());
Employee result = repository.save(employee);
logger.info("PUT: Trying to replace + " + employee);
logger.info("PUT: replaced " + employee + " with " + result);
return result;
})
.orElseGet(() -> {
newEmployee.setId(id);
Employee result = repository.save(newEmployee);
logger.info("PUT: Trying to add" + newEmployee);
logger.info("PUT: add " + result);
return result;
});
}
卷曲命令:
curl -X PUT localhost:8080/employees/234 -H 'Content-type:application/json' -d '{"name": "Samwise Gamgee", "role": "gardener"}'
结果:
{"id":3,"name":"Samwise Gamgee","role":"gardener"}
日志:
2021-08-17 15:53:34.956 INFO 34321 --- [nio-8080-exec-1] payroll.EmployeeController : PUT: Trying to addEmployee{id=234, name='Samwise Gamgee', role='gardener'}
2021-08-17 15:53:34.956 INFO 34321 --- [nio-8080-exec-1] payroll.EmployeeController : PUT: add Employee{id=3, name='Samwise Gamgee', role='gardener'}
我的问题是:是否有可能在 Employee 实体中启用手动 id 字段创建?如果可以,如何启用?
编辑: 确切地说,我想制定如下生成策略:
- 如果在新的
Employee中没有指定id,数据库应该使用某种自动生成策略来生成它——它也应该在任何可能的故障情况下发生,例如应用正在尝试使用id保存对象,该对象已在 db 中出现。 - 如果没有,请从新对象中获取
id。
【问题讨论】: