【问题标题】:What is the difference between Unidirectional and Bidirectional JPA and Hibernate associations?单向和双向 JPA 和 Hibernate 关联有什么区别?
【发布时间】:2011-07-18 15:54:22
【问题描述】:

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

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

区别在于组是​​否持有用户的引用。

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

【问题讨论】:

  • 该组现在将知道它包含哪些用户。我认为这绝不是一个小区别。
  • 在更新方面,双向关系对我来说变得很混乱。 :)
  • 这可能会有所帮助:thorben-janssen.com/…

标签: java hibernate jpa orm associations


【解决方案1】:

我不能 100% 确定这是 only 的区别,但这是 主要的 区别。 Hibernate 文档还建议进行双向关联:

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

具体来说:

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

我个人对这个一揽子建议有一个小问题——在我看来,在某些情况下孩子没有任何实际理由了解其父母(例如,为什么订单商品需要 了解它所关联的顺序?),但我确实在合理的时间内看到了它的价值。而且由于双向性并没有真正伤害任何东西,我不觉得坚持它太令人反感。

【讨论】:

  • 双向性在某些情况下会受到伤害,正如 axtavt 所解释的那样!我会非常小心映射到 Hibernate 实体中的每个关系!除非您确切地知道自己在做什么,否则您最终可能会在 Hibernate 中加载所需的无穷无尽的时间。仔细考虑用例,为不同的用例使用不同的模型类。前任在事物列表中,我不需要所有相关对象,只需要标签和 ID。因此,对我来说,列表实体与详细实体不同(而且非常简单)。
【解决方案2】:

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

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

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

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

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

另请参阅:

【讨论】:

  • 嗨,谢谢,看来您是休眠专家,因为您已经回答了我的问题:stackoverflow.com/questions/5350770/…。现在我不确定关系是否成立,因为我不能在评论中写更多,所以我在这里发布dpaste.de/J85m。如果可能,请检查一下。:)
  • @hguser:如果你最终决定建立双向关系,我认为最好从addUser() 调用setGroup() 以保持双方一致。
  • 不调用group.addUser()里面的setGroup()怎么样?
  • @hguser:关系不会持久,请参阅答案中的第 2 点。不带addUser()也可以调用setGroup(),但是会导致内存中对象的状态不一致。
  • 我发现我无法正确映射,你能抽出时间在github上检查我的项目吗?这是一个小项目。
【解决方案3】:

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

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

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

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

【讨论】:

    【解决方案4】:

    有两个主要区别。

    访问关联方

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

    因此,对于单向@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

    【讨论】:

    • 但据我所知,父方始终是拥有外键的一方。这两句话在我看来是矛盾的。 from the child side where the foreign key resides.from the parent side where the foreign key resides.
    • FK 总是在子端。单向 OneToMany 管理可以在连接表中的子表中的 FK。点击链接了解更多详情。
    猜你喜欢
    • 1970-01-01
    • 2012-04-10
    • 2012-07-31
    • 2011-08-06
    • 2021-09-08
    • 2017-08-19
    相关资源
    最近更新 更多