Hibernate:双向性与单向性,取决于关系

时间:2013-08-12 15:00:39

标签: java hibernate

阅读关于Hibernate的维基页面我详细阐述了一些令人困惑的结论:

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).

这些陈述是真的吗?你有什么例子可以解释为什么在某些情况下建议使用单向性,而在其他情况下则建议使用双向性?

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

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

1 个答案:

答案 0 :(得分:1)

请注意"双向性"在Hibernate的上下文中意味着在您的Java类中,关系的两端都保持与另一方的链接。它对底层数据库模式没有影响(除了索引集合的情况,见下文),它只是你是否希望Java方面反映它。

对于你的所有结论,"推荐"实际上,转换为"考虑到您的业务逻辑,它通常最终会有意义,您可以这样做#34;。

您真的想仔细阅读Hibernate Core Reference Manual的第7章和第8章。

  1. 如果您需要,建议您这样做。指定双向关系会带来很多便利;特别是可以在业务逻辑中从两端导航关系。但是,如果你真的不需要这样做,那就什么都没有了。使用最适合的情况。在实践中,我发现我想要更频繁地指定与Hibernate的关系的两端 - 但它不是规则,而是它反映了我想要完成的事情。

  2. 这是真的。在多对一(或一对多)关系中,它是可选的。请考虑以下架构:

    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 - 到 - 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,而在另一种情况下,它不会填充{{1}}。如果您必须获得任何给定用户的帖子的集合,您将需要使用这样的双向关系,而不是显式构建HQL查询。根据您关系中的反向/插入/更新/级联选项,您还可以通过修改用户的帖子集来添加和删除帖子,这可能更准确地反映您的业务逻辑(或不!) 。

    我指定非索引集合不会影响底层架构的原因是因为如果要使用像列表这样的有序索引集合,则必须添加额外的列表索引字段到forumPosts表(虽然你不必将它添加到ForumPost DAO类)。

  3. 这是事实,但并不是一项要求,而且比这更深。与上述相同。双向性通常存在于多对多中。使用第三个连接表实现多对多关系。您可以在关系的两侧指定此表的详细信息。你可以简单地指定一方的关系,现在它是一个单向的关系。同样,无论你是否告诉 Hibernate关于映射是决定它的单向还是双向(在Hibernate的上下文中)。在这种情况下,除非您使用有序索引集合,否则它对底层架构也没有影响。实际上,Hibernate参考手册中的many-to-many example是单向设置。

    实际上,拥有单向的多对多关系会很奇怪,除非您正在使用现有的数据库模式,并且您的特定应用程序的业务逻辑不需要关系中的一方。但是,通常情况下,当您确定需要多对多关系时,您已经决定,因为您需要在关系的两个方面维护一组引用,并且您的DAO类将反映出来需要。

    因此,正确的结论是只是&#34;双向性通常出现在多对多的#34;中,而是#34;如果你设计了一个数据库,那么一个连接表,但你的业务逻辑只使用单向关系,你应该质疑你的模式是否适合你的应用程序(而且很可能是)&#34;。

  4. 事实并非如此。与上述所有要点完全相同。如果您需要从两侧导航一对一关系,那么您希望将其设置为双向(指定映射到Hibernate的两侧)。如果没有,那么你将它单向化(不要指定映射到Hibernate的两侧)。这再次归结为您的业务层中有意义的事情。

  5. 我希望有所帮助。我离开了很多的错综复杂的东西。你真的应该阅读Hibernate文档 - 它没有特别好组织,但是第7章和第8章将告诉你关于集合映射需要知道的一切。

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