javaspringspring-boothibernatespring-data-jpa

Springboot JPA adding an associated entity to a new entity in a ManytoOne asssociation


I have an @ManyToOne relationship between an Employee and Department. Every time I add a new employee to the department, I need to update a counter on the department entity for the total # of employees.

Whenever a new employee is added, I am retrieving the Department entity from the manager Employee entity, update the counter and then setting the Department entity on the new Employee entity and calling save() on the EmployeeRepository with the new Employee entity. However, this is throwing me a "detached entity passed to persist" error. I have the @Cascade set to @Cascade.ALL on the department_id field in the Employee entity which works when the 1st employee is added the Department gets created automatically. The issue happens when i am trying to retrieve the Department entity from an existing employee and attaching it to a new employee and trying to do a save on the new Employee entity.

Code looks like below:

@Entity
@Table(name = "employee")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EmployeeEntity implements Serializable {
    
    @Id
    @SequenceGenerator(name = "employee_id_seq", sequenceName = "employee_id_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "employee_id_seq")
    @Column(name = "id", updatable = false)
    private Integer id;

    @JdbcTypeCode(SqlTypes.Long)
    @Column(name = "employee_id")
    private Long employeeId;

    @ManyToOne
    @Cascade({CascadeType.ALL})
    @JoinColumn(name = "department_id", nullable = false)
    private DepartmentEntity departmentEntity;
 
    public EmployeeEntity(Long employeeId, DepartmentEntity departmentEntity) {
        this.employeeId = employeeId;
        this.departmentEntity = departmentEntity;
    }
}

@Entity
@Table(name = "department")
@Data
@NoArgsConstructor
public class DepartmentEntity implements Serializable {
    @Id
    @SequenceGenerator(name = "department_id_seq", sequenceName = "department_id_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "department_id_seq")
    @Column(name = "id", updatable = false)
    private Integer id;

    @JdbcTypeCode(SqlTypes.Integer)
    @Column(name = "num_employees", nullable = false)
    private Integer numEmployees;

}
// code execution
@Transactional
public void addEmployee(employeeId, managerId) {
    Employee manager = empRepository.findById(managerId);
    
    Department empDept = manager.getDepartmentEntity()
    empDept.numEmployees++;
    
    Employee associate = new EmployeeEntity(employeeId, empDept);
    
    empRepository.save(associate); // this throws the exception
}

Any thoughts on how this can be addressed? Thank you in advance!


Solution

  • You will get an error only if addEmployee is invoked from the same class that has the method