我有一个关于 JPA-2.0(提供者是 Hibernate)关系及其在 Java 中的相应管理的问题。假设我有一个部门和一个员工实体:
@Entity
public class Department {
...
@OneToMany(mappedBy = "department")
private Set<Employee> employees = new HashSet<Employee>();
...
}
@Entity
public class Employee {
...
@ManyToOne(targetEntity = Department.class)
@JoinColumn
private Department department;
...
}
现在我知道我必须自己管理 Java 关系,如以下单元测试所示:
@Transactional
@Test
public void testBoth() {
Department d = new Department();
Employee e = new Employee();
e.setDepartment(d);
d.getEmployees().add(e);
em.persist(d);
em.persist(e);
assertNotNull(em.find(Employee.class, e.getId()).getDepartment());
assertNotNull(em.find(Department.class, d.getId()).getEmployees());
}
如果我遗漏了任何一个,e.setDepartment(d)
否则d.getEmployees().add(e)
断言将失败。到现在为止还挺好。如果我在两者之间提交数据库事务怎么办?
@Test
public void testBoth() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Department d = new Department();
Employee e = new Employee();
e.setDepartment(d);
d.getEmployees().add(e);
em.persist(d);
em.persist(e);
em.getTransaction().commit();
em.close();
em = emf.createEntityManager();
em.getTransaction().begin();
assertNotNull(em.find(Employee.class, e.getId()).getDepartment());
assertNotNull(em.find(Department.class, d.getId()).getEmployees());
em.getTransaction().commit();
em.close();
}
我还需要管理关系的双方吗?不,事实证明,我不必这样做。有了这个修改
e.setDepartment(d);
//d.getEmployees().add(e);
断言仍然成功。但是,如果我只设置另一边:
//e.setDepartment(d);
d.getEmployees().add(e);
断言失败。为什么?是因为 Employee 是关系的所有者吗?我可以通过不同的注释来改变这种行为吗?还是只是“OneToMany”的“One”一侧决定何时填充数据库中的外键字段?