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


135

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

由于在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;
}

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

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


7
该组现在将知道它包含哪些用户。我认为这绝不是一个小差异。
Satadru Biswas 2011年

5
在更新方面,双向关系对我来说很混乱。:)
diyoda_

Answers:


152

主要区别在于双向关系提供了双向导航访问,因此您无需显式查询即可访问另一侧。此外,它还允许您在两个方向上应用级联选项。

请注意,导航访问并不总是很好,尤其是对于“一对多”和“一对多”关系而言。想象一个Group包含数千个User的:

  • 您将如何访问它们?对于这么多Users,您通常需要应用一些过滤和/或分页,以便无论如何都要执行查询(除非您使用集合过滤,对我来说这看起来像是hack)。在这种情况下,某些开发人员可能倾向于在内存中应用过滤,这显然不利于性能。请注意,具有这种关系可以鼓励这类开发人员在不考虑性能影响的情况下使用它。

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

因此,我不同意“ 最佳实践”中的建议。您需要仔细设计双向关系,同时考虑用例(是否需要双向导航?)以及可能的性能影响。

也可以看看:


嗨,谢谢,似乎您是休眠专家,因为您已经回答了我的问题:stackoverflow.com/questions/5350770/…。现在我不确定该关系是否成立,因为我无法在评论中写出更多内容,因此我将其张贴在此处 dpaste.de/J85m。如果可能,请进行检查。:)
hguser 2011年

@hguser:如果你最终决定让你的关系是双向的,我认为这将是最好的呼叫setGroup()addUser()以保持双方是一致的。
2011年

如果不在group.addUser()内部调用setGroup()怎么办?
hguser

@hguser:关系不会持久,请参见答案中的第2点。您可以setGroup()不带调用addUser(),但这会导致内存中对象的状态不一致。
2011年

我发现我无法正确映射,您可以抽出一些时间在github上检查我的项目吗?这是一个小项目。
hguser 2011年

31

有两个主要区别。

访问关联方

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

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

如果您具有单向@OneToMany关联,则意味着您只能从外键所在的父侧访问该关系。

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

您还需要对双向关联使用添加/删除实用程序方法,以确保双方正确同步

性能

第二方面与性能有关。

  1. 因为@OneToMany单向关联的表现不如双向关联
  2. 对于@OneToOne双向关联,将导致母公司要获取热切如果Hibernate无法告诉代理是否应该分配或空值
  3. 对于而言@ManyToMany集合类型的Sets表现要比更好的有所不同Lists

11

就编码而言,双向关系的实现更为复杂,因为根据JPA规范5(第42页),应用程序负责使双方保持同步。不幸的是,规范中给出的示例没有给出更多细节,因此它没有给出复杂程度的概念。

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

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

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


9

我不是100%肯定这是唯一的区别,但这是主要区别。Hibernate文档还建议具有双向关联:

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

特别:

首选双向关联:单向关联更难以查询。在大型应用程序中,查询中的几乎所有关联都必须在两个方向上都是可导航的。

我个人对此总括性建议有一个小问题-在我看来,有些情况下孩子没有任何实际的理由要了解其父母(例如,为什么一个订单项需要知道其订单是什么)关联?),但我也确实在一段时间内看到了它的价值。而且由于双向性并没有真正损害任何东西,因此我认为它不会太令人反感。


正如axtavt所解释的,双向性在某些情况下可能会造成伤害!对于在Hibernate实体中映射的每个关系,我都会非常小心!除非您确切知道自己在做什么,否则最终可能会花费无穷的时间在Hibernate中加载内容。仔细考虑用例,并对不同的用例使用不同的模型类。F.ex. 在列表中,我不需要所有相关的对象,只需要标签和ID。因此,对我而言,列表实体与详细实体是不同的(并且非常简单)。
cslotty
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.