单向和双向JPA和Hibernate关联有什么区别?

时间:2011-03-19 07:28:02

标签: java hibernate jpa orm associations

单向和双向关联有什么区别?

由于在db中生成的表格都是相同的,所以我发现的唯一区别是双向关联的每一边都有一个引用另一边,而单向不是。

这是单向关联

public class User {
    private int     id;
    private String  name;
    @ManyToOne
    @JoinColumn(
            name = "groupId")
    private Group   group;
}

public class Group {
    private int     id;
    private String  name;
}

双向关联

public class User {
    private int     id;
    private String  name;
    @ManyToOne
    @JoinColumn(
            name = "groupId")
    private Group   group;
}
public class Group {
    private int         id;
    private String      name;
    @OneToMany(mappedBy="group")
    private List<User>  users;
}

区别在于该组是否持有用户的参考。

所以我想知道这是否是唯一的区别?这是推荐的吗?

4 个答案:

答案 0 :(得分:126)

主要区别在于双向关系提供双向导航访问,因此您可以在没有显式查询的情况下访问另一方。此外,它允许您向两个方向应用级联选项。

请注意,导航访问并不总是好的,特别是对于“一对多”和“多对多”关系。想象一下Group包含数千个User s:

  • 你会如何访问它们?有这么多User s,你通常需要应用一些过滤和/或分页,这样你无论如何都需要执行一个查询(除非你使用collection filtering,这看起来像是我的黑客攻击)。在这种情况下,一些开发人员可能倾向于在内存中应用过滤,这显然不利于性能。请注意,拥有这种关系可以鼓励这种开发人员使用它而不考虑性能影响。

  • 您如何向User添加新的Group?幸运的是,Hibernate在持久化时会查看关系的拥有方,因此您只能设置User.group。但是,如果要保持内存中的对象一致,还需要将User添加到Group.users。但它会使Hibernate从数据库中获取Group.users的所有元素!

所以,我不同意Best Practices的建议。您需要仔细设计双向关系,考虑用例(您是否需要双向导航访问?)以及可能的性能影响。

另见:

答案 1 :(得分:14)

有两个主要区别。

访问关联方

第一个与您将如何访问这种关系有关。对于单向关联,您只能从一端导航关联。

因此,对于单向@ManyToOne关联,这意味着您只能从外键所在的子端访问该关系。

如果您有单向@OneToMany关联,则表示您只能访问外键所在的父级关系。

对于双向@OneToMany关联,您可以从父级或子级两种方式导航关联。

您还需要use add/remove utility methods for bidirectional associations to make sure that both sides are properly synchronized

效果

第二个方面与表现有关。

  1. 适用于@OneToManyunidirectional associations don't perform as well as bidirectional ones
  2. 适用于@OneToOnea bidirectional association will cause the parent to be fetched eagerly if Hibernate cannot tell whether the Proxy should be assigned or a null value
  3. 适用于@ManyToManythe collection type makes quite a difference as Sets perform better than Lists

答案 2 :(得分:9)

我不是100%确定这是唯一的差异,但它是的区别。它还建议通过Hibernate文档进行双向关联:

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/best-practices.html

具体做法是:

  

首选双向关联:        单向关联更难以查询。在一个大   应用,几乎所有协会   必须可以双向导航   在查询中。

我个人对此一揽子建议有一点点问题 - 在我看来,有些情况下,孩子没有任何实际理由知道其父母(例如,为什么订单项需要< / em>知道它与之相关的顺序?),但我确实在其中看到了合理部分时间的价值。而且由于双向性并没有真正伤害任何东西,我觉得坚持不会太令人反感。

答案 3 :(得分:9)

在编码方面,双向关系实现起来比较复杂,因为应用程序负责根据JPA规范5(第42页)保持双方同步。不幸的是,规范中给出的例子没有提供更多细节,因此它没有给出复杂程度的概念。

当不使用二级缓存时,没有正确实现关系方法通常不是问题,因为实例在事务结束时被丢弃。

使用二级缓存时,如果由于错误实现的关系处理方法而导致任何内容损坏,这意味着其他事务也会看到损坏的元素(二级缓存是全局的)。

正确实现的双向关系可以使查询和代码更简单,但如果在业务逻辑方面确实没有意义,则不应该使用它。