首页 > 解决方案 > JPA Spring Boot Hibernate Rest API:为什么Hibernate在插入之前会删除?

问题描述

我想描述以下场景:我使用 Spring Boot 作为后端,使用 MySQL 数据库和 Angular 9 作为前端。

这是员工和预订之间的多对多关系。

MySQL

雇员:

emp_id 姓名
1 测试

预订:

book_id 属性
1 测试

book_emp:

emp_id book_id
1 1

到目前为止一切正常,但是当我将更多值发布到链接表时,所有其他元组都被删除。

book_emp:

emp_id book_id
1 2

结果应该是这样的:

emp_id book_id
1 1
1 2

安慰

Hibernate: insert into booking (hours, total, wadge_eur, year) values (?, ?, ?, ?)
Hibernate: delete from book_emp where emp_id=?
Hibernate: insert into book_emp (emp_id, book_id) values (?, ?)

为什么 Hibernate 从 book_emp 中删除?我已经尝试了 ManyToMany 注释类中所有可能的变体。不幸的是没有成功。我认为问题出在 RestController 上。

我之前尝试过 PUT,但结果与 POST 相同。

Spring Boot Employee.java

@ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
    @JoinTable(name = Constant.BOOK_EMP, joinColumns = @JoinColumn(name = Constant.EMP_ID, referencedColumnName = Constant.EMP_ID), 
            inverseJoinColumns = @JoinColumn(name = Constant.BOOK_ID, referencedColumnName = Constant.BOOK_ID), 
            uniqueConstraints = {
            @UniqueConstraint(columnNames = { Constant.EMP_ID, Constant.BOOK_ID }) 
            })
    @JsonBackReference(value = Constant.BOOKING)
    private Set<Booking> bookings;

Booking.java

@ManyToMany(mappedBy = "bookings")
       private Set<Employee> employees;

EmployeeController.java:

@PostMapping(Constant.EMPLOYEE + "/{id}")
    public Employee postEmployeeById(@PathVariable(value = "id") Long employeeId,
            @Valid @RequestBody Employee employeeDetails) throws ResourceNotFoundException {
        Employee employee = employeeRepository.findById(employeeId)
                .orElseThrow(() -> new ResourceNotFoundException("Employee not found for this id ::" + employeeId));
                
        employee.setBookings(employeeDetails.getBookings());
                
        return employeeRepository.save(employee);

EmployeeRepository.java

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {}

员工.service.ts

  updateEmployeeData(id: number, value: any): Observable<Object> {
    return this.httpClient.post(`${this.baseURL + this.empURL}/${id}`, value);
  }

如何告诉 Hibernate 停止删除?

标签: angularspring-boothibernaterestjpa

解决方案


[解析度]

员工类

//LOMBOK 
...
@EqualsAndHashCode(exclude = "bookings")
...

    @ManyToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
        @JoinTable(name = Constant.BOOK_EMP, joinColumns = @JoinColumn(name = 
         Constant.EMP_ID, referencedColumnName = Constant.EMP_ID, updatable = false, 
         insertable = false), 
            inverseJoinColumns = @JoinColumn(name = Constant.BOOK_ID, referencedColumnName = Constant.BOOK_ID, updatable = false, insertable = false), 
            uniqueConstraints = {
            @UniqueConstraint(columnNames = { Constant.EMP_ID, Constant.BOOK_ID }) 
            })
    @JsonBackReference(value = Constant.BOOKING)
    private Set<Booking> bookings;
    
    @JsonIgnore
    public boolean addEmpBook(Set<Booking> set) {
            return this.bookings.addAll(set);           
    }

预订舱位

//LOMBOK: 
...
@EqualsAndHashCode(exclude = "employees")
...
    
    @JsonIgnore
    @ManyToMany(mappedBy = "bookings")
    private Set<Employee> employees;

员工控制器

    @PostMapping(Constant.EMPLOYEE + "/{id}")
    public Employee postEmployeeById(@PathVariable(value = "id") Long employeeId,
            @Valid @RequestBody Employee employeeDetails) throws ResourceNotFoundException {
        Employee employee = employeeRepository.findById(employeeId)
                .orElseThrow(() -> new ResourceNotFoundException("Employee not found for 
                this id ::" + employeeId));
        
        employee.addEmpBook(employeeDetails.getBookings());
        return employeeRepository.save(employee);
    }
    

控制台休眠

Hibernate: insert into booking (hours, total, wadge_eur, year) values (?, ?, ?, ?)
Hibernate: insert into book_emp (emp_id, book_id) values (?, ?)

推荐阅读