18

我有一个实体 - 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")

结果我应该有user1inusers_1_tableuser2 in users_2_table

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

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

4

5 回答 5

36

前言:

即使在 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 被用作此片段的基础。官方来源 [ 4 ]

比赛后:

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

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

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

另一个案例:

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

来源

[1]如何使用hibernate/jpa注解将一个类映射到不同的表

[2]将两个相同的表(相同的模式...)映射到 Hibernate 中的相同实体

[3]如何将 2 个相同的表(相同的属性)映射到 1 个实体

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

[5] Hibernate 4:一个类映射两个表 - 如何在两个表上持久化一个对象?

[6] Hibernate Annotation for Entity 存在于超过 1 个目录中

于 2013-05-28T19:48:05.080 回答
4

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

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

对于替代方案。

于 2014-12-11T15:25:09.963 回答
1

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

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

这能达到什么目的?

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

费用是多少?

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

子类型化有好处吗?

  • 没有我能看到的

你应该这样做吗?

  • 我不这么认为!使用子类型和标准代码。
于 2013-05-29T10:22:35.013 回答
0

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

这是我在google后找到的一个示例,检查它是否可以帮助您实现:

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

于 2013-05-26T01:01:32.847 回答
0

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

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

于 2019-10-18T08:57:44.313 回答