java - hibernate :双向与单向,取决于关系

标签 java hibernate

在阅读有关Hibernate的Wiki页面时,我阐述了一些令人困惑的结论:

1) Bidirectionality is reccomended in one-to-many

2) Bidirectionality is optional in many-to-one

3) Bidirectionality is normally present in many-to-many

4) Unidirectionality is reccomended in one-to-one relationships, 
using as owner class the one with the primary key of the 
relation (not the foreign key).


这些说法正确吗?您是否有任何示例来说明为什么在某些情况下建议单向性而在其他情况下建议双向呢?

这是Wiki页面(在“概念”下阅读):

http://wiki.elvanor.net/index.php/Hibernate

最佳答案

请注意,在Hibernate上下文中,“双向性”意味着在Java类中,关系的两侧都保持到另一侧的链接。它对基础数据库模式没有任何影响(除非是索引集合,请参见下文),这只是您是否希望Java方面来体现这一点。

对于您的所有结论,“推荐”实际上转化为“通常会在考虑到您的业务逻辑的情况下才有意义,您会这样做。”

您确实想通读Hibernate Core Reference Manual的第7章和第8章。


如果需要,建议使用。指定双向关系会带来很多便利;特别是可以在业务逻辑中从两端导航关系。但是,如果您实际上不需要执行此操作,则没有任何收获。使用最适合这种情况的东西。在实践中,我发现我想经常指定与Hibernate的关系的两端-但这不是一条规则,而是反映了我想要完成的工作。
这是真的。在多对一(或一对多)关系中,它是可选的。考虑以下架构:

table: users
fields: userId, userName

table: forumPosts
fields: postId, userId, content



其中forumPosts.userIdusers的外键。您的DAO类可能是(为简洁起见,省略了getter / setter):

public class User {
    private long userId;
    private String userName; 
}

public class ForumPost {
    private long postId;
    private User user; 
    private String content;
}



如您所见,这是单向多对一关系(ForumPost -to- User)。 ForumPost链接到用户,但是User不包含ForumPosts列表。

然后,您可以向User添加一对多映射,以使其具有ForumPosts列表。如果您使用诸如集合之类的非索引集合,则这对数据库架构没有影响。仅通过指定Hibernate的两侧,就可以使其成为双向的(使用与上述完全相同的模式),例如:

public class User {
    private long userId;
    private String userName; 
    private Set<ForumPost> forumPosts;
}

public class ForumPost {
    private long postId;
    private User user; 
    private String content;
}



Hibernate现在将在必要时填充User.forumPosts(基本上使用SELECT * FROM forumPosts WHERE userId = ?)。双向与单向之间的唯一区别是,在一种情况下,Hibernate在ForumPosts中填充一组User,而在另一种情况下则不填充。如果您必须获得任何给定用户帖子的集合,则需要使用这样的双向关系,而不是显式构造HQL查询。根据关系中的反向/插入/更新/级联选项,您还可以通过修改用户的帖子集来添加和删除帖子,这可能更准确地反映了您的业务逻辑(或没有!)。

我之所以指定未编制索引的集合不影响基础架构的原因是,如果您想使用一个有序列的,建立索引的集合(如列表),则必须向forumPosts表中添加一个额外的列表索引字段(尽管您这样做不必将其添加到ForumPost DAO类中。
的确如此,但这不是必须的,而且要深得多。同上。双向性通常存在于多对多中。多对多关系是通过第三个联接表实现的。您可以在关系的两侧指定此表的详细信息。您根本无法在一侧指定关系,而现在它是单向关系。同样,是否告诉Hibernate映射关系决定了它是单向的还是双向的(在Hibernate的上下文中)。在这种情况下,除非您使用有序索引集合,否则它对基础架构也没有影响。实际上,Hibernate参考手册中的many-to-many example是单向设置。

实际上,除非您正在使用现有的数据库模式并且特定应用程序的业务逻辑不需要该关系的任何一方,否则具有单向多对多关系将是奇怪的。但是,通常,当您决定需要多对多关系时,您就决定要这样做,因为您需要在关系的两边都维护一个引用集合,而DAO类将反映这种需求。

因此,这里的正确结论不仅是“通常在多对多中存在双向性”,而是“如果您设计了一个具有联接表的数据库,但是您的业务逻辑仅使用了单向关系,您应该质疑模式是否适合您的应用程序(很可能是这样)”。
这不是真的。与上述所有要点完全相同。如果您需要从双方导航一对一关系,则需要使其成为双向的(指定映射到Hibernate的双方)。如果不是,则将其设为单向的(不要指定到Hibernate的映射的两面)。这再次归结为您的业务层中有意义的。


希望对您有所帮助。我遗漏了很多错综复杂的内容。您确实应该通读Hibernate文档-尽管它的组织方式不是特别好,但是第7章和第8章将告诉您有关集合映射的所有知识。

当我从头开始设计应用程序和数据库时,我会完全忘记Hibernate和数据库。我以对我的业务需求有意义的方式设置DAO,设计要匹配的数据库架构,然后设置Hibernate映射,然后对架构进行任何最终调整(例如,为有序集合添加索引字段),必要。

关于java - hibernate :双向与单向,取决于关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18190360/

相关文章:

java - 在一群程序员之间共享新版本 Java 源代码的最佳方式是什么?

java - Hibernate 在使用序列时生成负 id 值

java - 如何在 Hibernate 中复制 "SHOW TABLES"?

Wildfly 10 中的 Hibernate 4.3 支持

java - Android: fragment 交互监听器出错

java - Websocket 在 playframework 2 中向所有客户端发送数据

Java Retrofit 多请求单响应

java - 使用 StringTemplate 生成条件代码

java - 单向@OnetoMany 映射删除所有关系并重新添加剩余关系而不是删除特定关系

java - 在 session 期间更改 Hibernate Session.FlushMode