使用Java的OneToMany的最佳实践

时间:2014-03-01 21:47:20

标签: java sql hibernate design-patterns jpa

简短版本:

假设我在父母和孩子之间有一对多的关系。现在在Java代码中,最好的做法是读取父对象(从数据库中获取),并在其中应用一些名为addChild的方法,或者直接创建一个子项并在不读取父项的情况下保留它?

长版

假设我们有这个父母和孩子(来自http://en.wikibooks.org/wiki/Java_Persistence/OneToMany

@Entity
public class Employee {
  @Id
  @Column(name="EMP_ID")
  private long id;
  ...
  @OneToMany(mappedBy="owner")
  private List<Phone> phones;
  ...
}


@Entity
public class Phone {
  @Id
  private long id;
  ...
  @ManyToOne(fetch=FetchType.LAZY)
  @JoinColumn(name="OWNER_ID")
  private Employee owner;
  ...
}

现在考虑我有一个网页,员工可以在其中添加电话号码。所以我已经拥有父Employee的id,但是我没有完整的Employee对象。

1-我从数据库中获取整个Employee对象(当然是通过JPA映射)。然后我应用方法employee.addPhone(电话)或类似的东西。这导致两个查询。

2-我创建了手机对象,以及一个错误的员工对象,其中只包含员工的ID并且我坚持了吗?

这方面的最佳做法是什么?

1 个答案:

答案 0 :(得分:3)

最佳做法是维护协会的双方。这可以确保您不使用不一致的对象图。但是,它可能会降低服务的性能,特别是如果它只是创建一个链接到员工的新电话。实际上,它将加载员工及其所有现有手机的状态。

请注意,JPA只关心关联的所有者方:设置新Phone的员工足以在数据库中创建关联。

如果您选择使用第二个解决方案,则不应创建假的Employee对象。您应该从EntityManager获取Employee引用:

Employee e = em.getReference(Employee.class, employeeId);
Phone phone = new Phone();
phone.setEmployee(e);
em.persist(phone);

getReference()不会生成任何SQL查询。它返回一个未初始化的代理,这就是您所需要的。优点是,如果方法最终变得更复杂,并调用员工的任何方法,那么将加载员工的实际状态。