Given two entities Department
and Employee
forming a one-to-many relationship from Department
to Employee
.
Since the relationship is quite intuitive, I am leaving out the entity classes.
The following segment of code, simply persists an entity Employee
.
public void insert() {
Employee employee = new Employee();
employee.setEmployeeName("k");
Department department = entityManager.find(Department.class, 1L);
employee.setDepartment(department);
entityManager.persist(employee);
entityManager.flush();
List<Employee> employeeList = department.getEmployeeList();
employeeList.add(employee);
}
And the following method returns a list of employees associated with a particular department.
public List<Employee> getList() {
return entityManager.find(Department.class, 1L).getEmployeeList();
}
Both the methods are written in a stateless EJB using CMT (hereby not BMT) named let's say EmployeeService
.
A client application invokes these methods in sequence like so,
employeeService.insert();
List<Employee> employeeList = employeeService.getList();
for (Employee e : employeeList) {
System.out.println(e.getEmployeeId() + " : " + e.getEmployeeName());
}
The sout
statement in the foreach
loop above displays a newly added Employee
entity to List<Employee>
in Department
with a null
employeeId
in it given that the line entityManager.flush();
is not present in the very first code snippet.
EntityManager#persist(Object entity)
is not guaranteed to generate an id. An id is only guaranteed to be generated at flush time.
What happens is, if entityManager.flush();
is removed/commented, then the entity Employee
is added to the list of Employee
s (List<Employee> employeeList
) with a null
identifier in it (the primary key column in the underlying database table).
What is the usual way to maintain a bidirectional relationship? Is EntityManager#flush();
always needed every time an entity is to be added to a collection of entities being maintained by the inverse side of the relationship to generate an id associated with a newly persisted entity?
Also, is it always required to manually delete an Employee
from List<Employee>
(maintained by the inverse side of the relationship - Department
) while deleting an Employee
entity (using entityManager.remove(employee);
)?
EDIT : Entity classes :
Department :
@Entity
@Table(catalog = "testdb", schema = "", uniqueConstraints = {
@UniqueConstraint(columnNames = {"department_id"})})
public class Department implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "department_id", nullable = false)
private Long departmentId;
@Column(name = "department_name", length = 255)
private String departmentName;
@Column(length = 255)
private String location;
@OneToMany(mappedBy = "department", fetch = FetchType.LAZY)
private List<Employee> employeeList = new ArrayList<Employee>(0);
private static final long serialVersionUID = 1L;
// Constructors + getters + setters + hashcode() + equals() + toString().
}
Employee :
@Entity
@Table(catalog = "testdb", schema = "", uniqueConstraints = {
@UniqueConstraint(columnNames = {"employee_id"})})
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "employee_id", nullable = false)
private Long employeeId;
@Column(name = "employee_name", length = 255)
private String employeeName;
@JoinColumn(name = "department_id", referencedColumnName = "department_id")
@ManyToOne(fetch = FetchType.LAZY)
private Department department;
private static final long serialVersionUID = 1L;
// Constructors + getters + setters + hashcode() + equals() + toString().
}
When persisting the Employee
, you need to set both sides of the association.
In your Department
you should have this method:
public void addEmployee(Employee employee) {
employees.add(employee);
employee.setDepartment(this);
}
Make sure you cascade de PERSIST and MERGE events to your children association:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "department", orphanRemoval = true)
private List<Employee> children = new ArrayList<>();
and the persisting logic becomes:
Employee employee = new Employee();
employee.setEmployeeName("k");
Department department = entityManager.find(Department.class, 1L);
department.addEmployee(employee);