Spring REST - 无法强制 H2 数据库手动创建密钥

Posted

技术标签:

【中文标题】Spring REST - 无法强制 H2 数据库手动创建密钥【英文标题】:Spring REST - cannot force H2 database to create keys manually 【发布时间】: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 建议如果没有 Employeeid,则使用请求路径中的 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 addEmployeeid=234, name='Samwise Gamgee', role='gardener'
2021-08-17 15:53:34.956  INFO 34321 --- [nio-8080-exec-1] payroll.EmployeeController               : PUT: add Employeeid=3, name='Samwise Gamgee', role='gardener'

我的问题是:是否有可能在 Employee 实体中启用手动 id 字段创建?如果可以,如何启用?

编辑: 确切地说,我想制定如下生成策略:

    如果在新的Employee 中没有指定id,数据库应该使用某种自动生成策略来生成它——它也应该在任何可能的故障情况下发生,例如应用正在尝试使用 id 保存对象,该对象已在 db 中出现。 如果没有,请从新对象中获取 id

【问题讨论】:

【参考方案1】:

Employee 的属性 id 上的注释 @GeneratedValue 正在设置实体的 ID。您可以删除它并尝试一下。

【讨论】:

以上是关于Spring REST - 无法强制 H2 数据库手动创建密钥的主要内容,如果未能解决你的问题,请参考以下文章

具有多个数据源 Oracle 和 H2 的 Spring Boot

无法在 Spring 应用程序中登录 H2 控制台

无法加载驱动程序类: org.h2.Driver in spring boot

Spring Boot REST API 不支持的媒体类型

无法解析类或包 H2

JOOQ 强制类型无法通过 JPADatabase 代码生成生成 NUMERIC SQL 数据类型