I have a problem with mapping an entity (Employee) with @ManyToOne relation to the entity (Community) with @OneToMany relation.
When I assign an entity (Community) to an entity (Employee) where the value of Community is null, it works fine.
The problem arises, if the Employee already has an assigned value to the Community. When I change this value and save the changes, the Employee has got new value for the Community and this new Community has got this Employee in the collection. The only thing is that the old Community still has this Employee in the collection to, but it should be removed. This only happens when the database is restarted.
I tried to solve this problem using both @JoinColumn and @JoinTable, but the problem is the same. I would like to avoid removing an Entity from the old relation by calling JPA in update/create service method.
Are there any solutions to this problem?
Here is the code:
A Community
@Entity @Table(name = "community") public class Community implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @SequenceGenerator(name = "sequenceGenerator") @Column(name = "id") private Long id; @OneToMany(mappedBy = "community", orphanRemoval = true, cascade = CascadeType.ALL) private Set<Employee> employees = new java.util.LinkedHashSet<>(); public Long getId() { return this.id; } public Community id(Long id) { this.setId(id); return this; } public void setId(Long id) { this.id = id; } public Set<Employee> getEmployees() { return this.employees; } public void setEmployees(Set<Employee> employees) { if (this.employees != null) { this.employees.forEach(i -> i.setCommunity(null)); } if (employees != null) { employees.forEach(i -> i.setCommunity(this)); } this.employees = employees; } public Community employees(Set<Employee> employees) { this.setEmployees(employees); return this; } public Community addEmployees(Employee employee) { this.employees.add(employee); employee.setCommunity(this); return this; } public Community removeEmployees(Employee employee) { this.employees.remove(employee); employee.setCommunity(null); return this; }
A Employee.
@Entity @Table(name = "employee") public class Employee implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @SequenceGenerator(name = "sequenceGenerator") @Column(name = "id") private Long id; @ManyToOne(optional = false) @JoinColumn(name = "community_id") // @JoinTable(name = "rel_community__employees", // joinColumns = {@JoinColumn(name = "community_id", referencedColumnName = "id", nullable = false)}, // inverseJoinColumns = {@JoinColumn(name = "employee_id", referencedColumnName = "id", nullable = false)}) @Cascade({CascadeType.PERSIST, CascadeType.REFRESH) private Community community; public Long getId() { return this.id; } public Employee id(Long id) { this.setId(id); return this; } public void setId(Long id) { this.id = id; } public Community getCommunity() { return this.community; } public void setCommunity(Community community) { this.community = community; } public Employee community(Community community) { this.setCommunity(community); return this; }
Service Implementation for managing {@link Employee}.
@Service @Transactional public class EmployeeServiceImpl implements EmployeeService { @Override public EmployeeDTO save(EmployeeDTO employeeDTO) { Employee employee = employeeMapper.toEntity(employeeDTO); employee = employeeRepository.save(employee); return employeeMapper.toDto(employee); } @Override public EmployeeDTO update(EmployeeDTO employeeDTO) { Employee employee = employeeMapper.toEntity(employeeDTO); employee = employeeRepository.save(employee); return employeeMapper.toDto(employee); }
}