【问题标题】:Hibernate Mapping of Join Table with Meta Data连接表与元数据的 Hibernate 映射
【发布时间】:2012-11-02 20:22:50
【问题描述】:

我试图弄清楚如何通过一个包含一些元数据的连接表来映射两个表之间的关系。简而言之,三个表格代表一个表单的页面,每个页面可以包含任意数量的元素(问题)。出于某种原因,最初的开发人员决定元素可以用于多个表单。这意味着用于对页面上的元素进行排序的权重列位于连接表中。

我到底如何在 XML 中映射它? (注释不是一种选择。)

对于连接表,我猜是这样的:

<class name="com.foo.bar.model.db.ApplicationPageElements"  
       table="APPLICATION_PAGE_ELEMENTS">
    <composite-id name="id" class="com.foo.bar.model.db.ApplicationPageElementsKey">
        <key-property name="pageId" column="page_id"/>
        <key-property name="elementId" column="element_id"/>
    </composite-id>
    <property name="weight" type="java.lang.Long">
        <column name="WEIGHT" precision="0" />
    </property>
</class>

我的直觉让我想从 ApplicationPage 方面做这样的事情:

<set name="applicationElements" table="applicationPageElement">
    <key column="page_id"/>
    <many-to-many column="element_id" unique="true"
          class="com.foo.bar.model.db.ApplicationElements" />        
</set>

这就是我下巴松弛,盯着屏幕哭泣的地方。

我们正在使用 .hbm.xml 文件来映射我们的数据库。我们还决定不更改我们的数据库。

关于如何在 XML 中映射它的任何想法?

【问题讨论】:

  • 我讨厌 XML 映射,所以我无法回答这个问题。但我可以说的是,这里没有多对多。您在 Page 和 ApplicationPageElement 之间有一个 OneToMany,在 Element 和 ApplicationPageElement 之间有另一个 OneToMany。不要使用复数形式来命名实体。实体的每个实例代表一个实体,而不是多个实体。
  • 您看到的一些东西是旧版应用程序的东西。每次我写 ApplicationElements 时,我都会在内心深处死去。

标签: java hibernate join


【解决方案1】:

不要将 application_page 和 application_element 之间的关系视为多对多的关系,而是将其视为从 application_page 到 ApplicationPageElements 的一对多关系以及从 application_element 到 ApplicationPageElements 的一对多关系。

在您的 application_page xml 映射中添加:

<set name="applicationElements" inverse="true">
    <key column="page_id"/>
    <one-to-many class="ApplicationPageElements"/>
</set>

page_id 构成连接表主键的一部分。因此,将集合标记为反向。

您对连接表的映射是正确的。但是,通过上述更改连接表的当前映射,您可以从 application_page 导航到 ApplicationPageElements。要从 application_page 导航到 application_element(通过 ApplicationPageElements),请在连接表映射中添加多对一关系。

<class name="com.foo.bar.model.db.ApplicationPageElements"  
       table="APPLICATION_PAGE_ELEMENTS">
    <composite-id name="id" class="com.foo.bar.model.db.ApplicationPageElementsKey">
        <key-property name="pageId" column="page_id"/>
        <key-property name="elementId" column="element_id"/>
    </composite-id>
    <property name="weight" type="java.lang.Long">
        <column name="WEIGHT" precision="0" />
    </property>
    <many-to-one name="elements" class="ApplicationElements" 
    column="element_id" not-null="true" insert="false" update="false"/>
    <many-to-one name="page" class="ApplicationPage" 
    column="page_id" not-null="true" insert="false" update="false"/>
</class>

请注意,在上面的多对一映射中,insert 和 update 属性都设置为 false。这是必要的,因为列被映射了两次,一次在复合键中(负责插入值),另一次用于多对一关联。

上述用例在《Java Persistence with Hibernate》一书中有详细提及。

【讨论】:

  • 非常感谢您的回答和详细的解释。问题:在 XML 的第一个块中,您的意思是写 name="applicationPageElements" 吗?听起来您在说我应该拉回连接表条目的列表,然后从中获取元素列表。 (通过这种方式,我将能够操纵“重量”列。)对吗?没有?
  • 是的。我的意思是 name="applicationPageElements"。我只是从您的 xml 中保留了名称,因为名称可以是任何东西。是的,您应该从 applicationPage 中提取连接表条目的列表。对于列表中的每个连接条目,您将获得 一个 applicationElement。这么晚才回复很抱歉。我没有收到有关您的评论的任何通知。
  • 我最初使用“applicationElement”是因为我想检索 ApplicationElement 对象的集合。我对连接表不是很感兴趣。在连接表上没有“权重”(或其他元数据)列的其他用例中,连接表的机制被 Hibernate 从程序员那里“隐藏”了。我希望这个用例存在这样的解决方案。但我猜你是说它没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
  • 1970-01-01
  • 1970-01-01
  • 2016-07-02
  • 2022-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多