【问题标题】:hibernate two tables per one entity每个实体休眠两个表
【发布时间】:2013-05-26 00:54:17
【问题描述】:

我有一个实体 - User。由User.class描述。

Hibernate 为每个实体创建一个表,因此当我调用 session.save(user) 时,我的数据始终保存到此表中。

现在我需要另一个表来存储相同User 类型的数据,并且我只需要将我的实体保存到该表中。

数据结构(类似这样):

table users_1_table{
  string id;
  string username;
}

table users_2_table{
  string id;
  string username;
}

使用这个:

session.save(user1,"users_1_table")
session.save(user2,"users_2_table")

结果我应该在users_1_table 中拥有user1,在users_2_table 中拥有user2。

由于系统限制,我不能将这两个对象放在一个表中。 (即使创建额外的字段也是个坏主意)。

我可以在没有子类的情况下做到这一点吗?使用编程方式休眠配置?

【问题讨论】:

  • 为什么要在没有子类化的情况下这样做?将其子类化为 Hibernate 的解决方案。如果你想在没有子类化的情况下这样做,那么你使用了错误的工具。

标签: java spring hibernate sqlite hibernate-annotations


【解决方案1】:

前言:

即使在 SO 上,这也是一个被广泛询问的问题,而且答案也与 Subclass 或实际上是 SuperClass 方法有关(例如 [1])

实际答案:

在这些帖子 [2]、[3] 上,他们建议使用带有 EntityName 参数的 xml 映射。

因此,使用 xml 进行映射不需要超类,只需将 EntityName 参数赋予两个相同的映射即可。

示例映射:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
   <class name="DomainModel.User, DomainModel"
     table="User1Object" entity-name="User1Object">  
         <id name="_id" access="field" column="id">
             <generator class="assigned"/>
         </id>
        <property name= ...>
 </class>
 <class name="DomainModel.User, DomainModel"
     table="User2Object" entity-name="User2Object">
         <id name="_id" access="field" column="id">
            <generator class="assigned"/>
         </id>
        <property name= ...>
</class>
</hibernate-mapping>

然后根据您需要的实体类型,您可以调用适当的会话方法:

_session.Save("User1Object", user1)

或

_session.Save("User2Object", user2)

帖子 2 和 3 被用作此 sn-p 的基础。官方来源[4]

赛后:

第一个问题的答案实际上是链接到这篇文章 [5] 有不同的方法:

您对对象的第一个实例说再见,将数据克隆到新实例并以不同的名称持久保存。因此,没有违反 Hibernate 逻辑和每个人的内容:两个表中的相同数据并且没有使用子类。

嗯,那个方法的实现或者代码或者可信度是某某,我也没有测试过。

另一种情况:

在这篇文章 [6] 中,还有一个人试图用更简单的方法来挑战超类方法,但同样,最可信的答案表明,不可能以另一种方式解决,官方非xml方式就是说的子类方式。

来源

[1]How to map one class to different tables using hibernate/jpa annotations

[2]Map Two Identical tables ( same schema...) to same entity in Hibernate

[3]How to map 2 identical tables (same properties) to 1 entity

[4]http://docs.jboss.org/hibernate/core/3.2/reference/en/html/mapping.html#mapping-entityname

[5]Hibernate 4: One class mapping Two tables - How to persist one object on both tables?

[6]Hibernate Annotation for Entity existing in more than 1 catalog

【讨论】:

  • 可以在eclipse中生成吗?
  • Eclipse 站点 (myeclipseide.com/documentation/quickstarts/hibernate/#5-7) 有一个用于其逆向工程工具的指令表,并有一个选项 Create abstract class 和解释 '为每个数据对象生成一个抽象超类。抽象类将在后续生成过程中被覆盖,但相应的子类不会被覆盖。' 据我了解,这至少会产生一些有用的东西..
  • 如果实体 B 是 A 和 C 的成员(多对上)并且我保存 A 和 C 的实例,而不是直接保存 B,我该怎么办。
  • 选择查询在这种情况下如何工作。假设我使用此方法将实体映射到两个不同的表,它们相差一列,现在我想从两个表中获取所有行,我必须使用某种连接查询还是会自动获取行从两个表?
【解决方案2】:

它还可以使用默认实体和替代实体:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
   <class name="DomainModel.User, DomainModel"
     table="User1Object">  
         <id name="_id" access="field" column="id">
             <generator class="assigned"/>
         </id>
        <property name= ...>
 </class>
 <class name="DomainModel.User, DomainModel"
     table="User2Object" entity-name="User2Object">
         <id name="_id" access="field" column="id">
            <generator class="assigned"/>
         </id>
        <property name= ...>
</class>
</hibernate-mapping>

默认的可以使用方法

_session.Save(user1)

和

_session.Save("User2Object", user2)

换一个。

【讨论】:

    【解决方案3】:

    您可以使用配置来做到这一点:

    • 为同一个实体类name创建两个映射,但给它们不同的逻辑entity-name和表名称。
    • 然后使用 Session 方法提供 entityName 作为参数来区分另一个。

    这样做有什么作用?

    • “虚拟子类型化”
    • 将数据检索到类型时,必须指定一个entity-type或另一个(因此暗示一个表或另一个)
    • 当您修改并保存数据时,您必须指定相同的 entity-type - 尝试使用不同的 entity-type 进行更新应被休眠拒绝。否则,修改后的实体将已经填充了一个标识符,因此 hibernate 将尝试更新而不是插入,但这会在数据库中失败 - 尝试更新表中从未存在的数据。
    • 这会导致隔离 - 在处理一个实体或实体列表时,您必须承诺使用一种实体类型,并且不能将两者混合使用。即“虚拟子类型化”

    费用是多少?

    • 它提供了非常弱的类型。编译器和运行时没有指示真正的子类型。错误正在等待发生,可能很难调试。
    • 这是非标准的。 JPA 已经避开了这一点,我相信它不会被纳入考虑范围,这是有充分理由的。
    • 您必须使用 XML,而不是注释。
    • 您必须调用异常方法,包括“实体类型”参数。

    子类型化有什么好处吗?

    • 我看不到

    你应该这样做吗?

    • 我不这么认为!使用子类型和标准代码。

    【讨论】:

      【解决方案4】:

      虽然我没用过但是hibernate中有一个Secondary Table的概念。 @SecondaryTables 是 hibernate 中的注解,一个实体可以通过它映射多个表来获取数据。获取数据的实体应该有 @SecondaryTables 注释。它根据主键和外键以及唯一约束来关联辅助表。

      这是我在google后发现的一个示例,检查它是否有助于您实现:

      http://www.concretepage.com/hibernate/secondarytables_hibernate_annotation.php

      【讨论】:

      • 用于将一个对象拆分为两个或多个表。我需要将整个对象保存在单独的表中。所以这不是答案。
      【解决方案5】:

      我知道很久以前有人问过这个问题。但我想建议一种替代方式,而不使用任何休眠的东西。对于那些不想使用xml配置的人。

      用公共列的getter和setter方法声明一个接口,然后让你的两个实体类实现这个接口。 照常保留这两个实体类中的映射注解,然后在您的代码中,您可以改为调用该接口的方法。

      【讨论】:

        猜你喜欢
        • 2017-07-17
        • 2014-05-03
        • 1970-01-01
        • 2018-03-14
        • 2011-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多