У меня есть вопрос об отношениях 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);
утверждения не верны. Зачем? Это потому, что Сотрудник является владельцем отношения? Могу ли я изменить это поведение, комментируя по-другому? Или это просто всегда сторона «One» в «OneToMany», которая определяет, когда поле внешнего ключа в базе данных заполнено?