【问题标题】:Multiple one-to-many relationships to same entity type and table?与同一实体类型和表的多个一对多关系?
【发布时间】:2015-08-19 23:28:45
【问题描述】:

我有一个有趣的用例,我希望 Hibernate 管理与同一实体类型的多个一对多关系。

例如:BookShelf fictionBooksBook 的关系,还有 BookShelf nonFictionBooks 映射到图书。 Hibernate 映射看起来像这样:

<class name="com.example.BookStore" table="BOOK_SHELF">
    <id name="id" type="long" column="bookShelfId">
        <generator class="native" />
    </id>
    <set name="fictionBooks" table="SHELF_BOOK" cascade="all-delete-orphan" lazy="false">
        <key column="bookShelfId" />
        <one-to-many class="com.example.Book" />
    </set>
    <set name="nonFictionBooks" table="SHELF_BOOK" cascade="all-delete-orphan" lazy="false">
        <key column="bookShelfId" />
        <one-to-many class="com.example.Book" />
    </set>
</class>
<class name="com.example.Book" table="SHELF_BOOK">
    <id name="id" type="long" column="shelfBookId">
        <generator class="native" />
    </id>
    <property name="name" not-null="true" unique="true"/>
</class>

有没有办法让关系所有者 BookShelf 指定一些可用于区分小说和非小说书籍的 discriminator 值?如果可能,鉴别器将作为附加列存储在 SHELF_BOOK 表中,Hibernate 会自动对其进行过滤。

有没有一种方法可以做到这一点,而无需借助 多对多 关联或使用 每类表策略扩展 Book 实体?

【问题讨论】:

    标签: mysql hibernate jpa


    【解决方案1】:

    理想情况下,您应该在 SHELF_BOOK 表中有一个“类型”或“标志”列,指示该书是小说还是非小说。

    假设你已经添加了这个“类型”列,那么我认为你可以在集合中指定一个过滤语句:

    <set name="fictionBooks" table="SHELF_BOOK" cascade="all-delete-orphan"   lazy="false">
        <filter name="myfilter" condition=":type = 'FICTION'"/>
        <key column="bookShelfId" />
        <one-to-many class="com.example.Book" />
    </set>
    

    可以参考http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#objectstate-filters

    【讨论】:

    • 这实际上是一个不错的解决方案。不知道 是关系中的一个选项。如果我没有更好的选择,明天会接受这个答案!
    • 在您的情况下更简单的是使用@org.hibernate.annotations.Where,但想法是一样的。
    【解决方案2】:

    根据您发布的内容,我可以说,为了实现您想要的,您需要修改您的关系所有者 BookShelf 以仅存储对 Book 的引用并添加属性,比如 bookType,到 Book 实体。

    <class name="com.example.BookStore" table="BOOK_SHELF">
        <id name="id" type="long" column="bookShelfId">
            <generator class="native" />
        </id>
        <set name="books" table="SHELF_BOOK" cascade="all-delete-orphan" lazy="false">
            <key column="bookShelfId" />
            <one-to-many class="com.example.Book" />
        </set>
    </class>
    
    
    <class name="com.example.Book" table="SHELF_BOOK">
        <id name="id" type="long" column="shelfBookId">
            <generator class="native" />
        </id>
        <property name="name" not-null="true" unique="true"/>
        <property name="bookType" not-null="true"/>
    </class>
    

    没有其他方法(除了ManytoMany)可以通过查看BookShelf实体来找出书的类型。您还可以使用单表策略,它会自动将鉴别器添加到插入的值中,但为了做到这一点,您需要为 FictionalBookNonFictionalBook 创建两个单独的类。

    【讨论】:

    • 这个愚蠢的 Book 示例是对实际问题的严重过度简化——FictionalBook 与 NonFictionalBook 的用途有很大不同,因此将它们结合起来是没有意义的。
    • 我还考虑了 FictionalBook 和 NonFictionalBook 的具体类,所以我可以使用鉴别器,但是实现两个完全空的类似乎是错误的。
    猜你喜欢
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多