当前位置: 首页 > 面试题库 >

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

范楚
2023-03-14
问题内容

我有一个关于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);

断言失败。为什么?是因为雇员是关系的所有者?我可以通过不同的注释来更改该行为吗?还是确定数据库中的外键字段何时被填充的总是“ OneToMany”的“
One”侧?


问题答案:

JPA中的实体关系具有拥有和相反的一面。数据库更新由拥有方的状态确定。在这种情况下,Employee由于该mappedBy属性,是拥有方。

根据JPA 2.0规范:

2.9实体关系

关系可以是双向的或单向的。双向关系既具有拥有侧又具有逆(非拥有)侧。单向关系只有一个拥有方。关系的拥有方确定数据库中该关系的更新,如3.2.4节所述。

以下规则适用于双向关系:

* 双向关系的反面必须通过使用OneToOne,OneToMany或ManyToMany批注的mappingBy元素来引用其所属的面。mapledBy元素指定实体中作为关系所有者的属性或字段。
* 一对多/多对一双向关系的多面必须是拥有方,因此无法在ManyToOne批注上指定mappingBy元素。
* 对于一对一的双向关系,拥有方对应于包含相应外键的方。
* 对于多对多双向关系,任何一方都可以是拥有方。




 类似资料:
  • 问题内容: 我想在两个实体(消费者和政策)之间建立一对多关系。一个消费者应该有几项政策。 这是我希望拥有的Consumer JSON对象的示例: 这是我到目前为止所拥有的: 政策实体 消费者实体 我认为这并不难,但是我现在尝试了几个小时而无法完成。我是Spring的新手,所以如果有人能够帮助我,我将非常感激! 问题答案: @Entity public class Consumer { 不是必需的,

  • 问题内容: 假设我与用户和项目之间存在多对多关系:一个用户可能属于多个项目,而一个项目可能具有多个用户。此关系在表中编码: 这是我的问题:给定一组用户(user1,user2,…),我想选择给定用户集为其所有用户的子集的所有项目。 例如,如果我在下面插入数据,然后询问用户1和2的所有项目,则查询应仅返回项目1。 (如果最好的解决方案恰巧是非标准的,那么我使用的是PostgreSQL。) 编辑: 为

  • 我希望在消费者和政策这两个实体之间建立一对多关系。一个消费者应该有几个政策。 这是我想要的一个消费JSON对象的例子: 这就是我到目前为止所做的: 政策实体 消费者实体 我想没那么难,但我已经试了几个小时了,还是做不到。我刚到Spring,所以如果有人能帮助我,我会非常感激!

  • 问题内容: 也许这是一个愚蠢的问题,但这困扰了我。 我有一个从员工到车辆的双向一对多关系。当我第一次将Employee保留在数据库中时(即它没有分配的ID),我也希望保留其关联的Vehicles。 目前,这对我来说很好,除了我保存的Vehicle实体没有自动映射关联的Employee,并且在数据库中Vehicle表中的employee_id外键列为空。 我的问题是,是否可以在雇员本身被保留的同时保

  • 问题内容: 什么是“阻抗不匹配”,它与数据库有何关系? 问题答案: 引用hacked.com 想象一下,您有一个通常使用AAA电池的低电流手电筒。不要在家中尝试此操作,但是假设您可以将汽车电池连接到手电筒上。小电流手电筒可怜地输出大电流电池能够产生的一部分光能。同样,如果将AAA电池连接到蝙蝠侠的聚光灯上,也会得到较低的输出。但是,将AAA电池与手电筒搭配使用,它们将以最高效率运行。 因此,将讨论