Search code examples
spring-bootjpaspring-data-jpaspring-data

Spring JPA delete entity not working when iterating


I am trying to delete an entity using its remove method of its repository from another service class, but it is not getting deleted. Below code works when I hard code the Id:

long id = 1234;
Optional<Employee> employeeOptional = employeeRepository.findById(id);
Employee employee = employeeOptional.get();
employeeRepository.delete(employee);

Above code is working fine, but if I try with below code, deletion is not happening.

for (Employee employee : department.getEmployees()) {
     if (employee.getRole().equals("Manager")) {
        employeeRepository.delete(employee);
     }
}

I am trying the code from DepartmentServiceImpl class, but above is not working, but same when id is hardcoded it works.

Inside Department I have relationship like below,

  @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "deal")
  private Set<Employee> employees= new HashSet<>();

And inside Employee I have like below,

  @ManyToOne
  @JoinColumn(name = "department_id", referencedColumnName = "department_id")
  private Department department;

How can I fix this issue?


Solution

  • You are attempting to delete Employees, but your entities still have references to each other.

    A better way to delete an employee is to use orphan removal and remove the employee from the collection which will trigger a delete.

    Also mappedBy = "deal" should be the name of the attribute on the owning side of the relationship so this should be mappedBy = "department"

    @OneToMany(
        cascade = CascadeType.ALL,
        mappedBy = "department",
        orphanRemoval = true
    )
    private Set<Employee> employees= new HashSet<>();
    

    add a method to Department to remove the Employee and keep the bidirectional relationship in sync by also removing Department from Employee

    public void removeEmployee(Employee employee) {
        employees.removeEmployee(employee);
        employee.setDepartment(null);
    }
    

    you can then remove the 'Managers' from your Employees collection which should trigger the delete statements

    List<Employee> managers = department.getEmployees.stream()
                    .filter(e -> e.getRole().equals("Manager"))
                    .collect(Collectors.toList());
    
    for (Employee manager : managers) {
        department.removeEmployee(manager);
    }