gpt4 book ai didi

java - JPA:一对多关系中阻抗不匹配的问题

转载 作者:搜寻专家 更新时间:2023-11-01 01:11:40 24 4
gpt4 key购买 nike

我对 JPA-2.0(提供程序是 Hibernate)关系及其在 Java 中的相应管理有疑问。假设我有一个 Department 和一个 Employee 实体:

@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”端?

最佳答案

我不知道您的测试试图证明什么,但事实是您在使用双向关联时必须处理关联的两边。不这样做是不正确的。时期。

更新:虽然 axtavt 提到的规范引用当然是准确的,但我坚持认为,您绝对必须设置双向关联的双方。不这样做是不正确的,并且在第一个持久性上下文中您的实体之间的关联中断JPA wiki book像这样说:

As with all bi-directional relationships it is your object model's and application's responsibility to maintain the relationship in both direction. There is no magic in JPA, if you add or remove to one side of the collection, you must also add or remove from the other side, see object corruption. Technically the database will be updated correctly if you only add/remove from the owning side of the relationship, but then your object model will be out of synch, which can cause issues.

换句话说,在 Java 中管理双向关联的唯一正确安全方法是设置链接的两端。这通常使用防御性链接管理方法来完成,如下所示:

@Entity
public class Department {
...
@OneToMany(mappedBy = "department")
private Set<Employee> employees = new HashSet<Employee>();
...

public void addToEmployees(Employee employee) {
this.employees.add(employee);
employee.setDepartment(this);
}
}

我再说一遍,不这样做是不正确的。您的测试之所以有效,是因为您在新的持久性上下文中访问数据库(即非常特殊的情况,而不是一般情况),但代码会在许多其他情况下中断。

关于java - JPA:一对多关系中阻抗不匹配的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3630439/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com