This blog article is part of a “series of blog articles” about common pitfalls using JPA and ways to avoid them. In this article, we describe issues with bidirectional relationships.
In a bidirectional relationship, each entity has a relationship field or property that refers to the other entity. In JPA a bidirectional relationship has an owing and an inverse side. The inverse side is the one having the mappedBy
element in the relationship annotation. In the following example Employee is the owning side of the bidirectional Employee ↔ Department relationship.
@Entity
public class Employee {
@ManyToOne
private Department department;
}
@Entity
public class Department {
@OneToMany(mappedBy="department")
private Set<Employee> employees;
}
According to the JPA spec “Bidirectional relationships … will be persisted based on references held by the owning side of the relationship”. For the example above this means: defining the relation by setting the department on the employee instance will result in the relationship being persisted. But if the relationship change is only on the inverse side, e.g. adding an employee to the department’s set of employees, there is no guarantee that this relationship is stored in the database.
// OK
emp.setDepartment(dept);
// Might not be stored in the database
dept.addEmployee(emp);
Recommendation: Make sure the owning side is changed, when modifying a bidirectional relationship.
You can find an example of this pitfall and its solution in the class RelationshipOwnerExperiment in this project: https://github.com/akquinet/jpapitfalls.git.