我有一个实体 - 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")
结果我应该user1
中的users_1_table
和user2
中的users_2_table
。
由于系统限制,我无法将这两个对象放在一个表中。 (即使创建额外的字段也是个坏主意)。
我可以在没有子类化的情况下这样做吗?使用programmaticaly hibernate配置?
答案 0 :(得分:33)
<强>前言强>
即使在SO上,这也是一个广泛提问的问题,而且答案也广泛地与Subclass
或实际SuperClass
方法相关(例如[1])
实际答案:
在这些帖子[2],[3]上,他们建议使用带有EntityName
参数的xml映射。
因此,使用xml进行映射不需要supeclass,只需将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&amp;使用3作为此片段的基础。官方来源[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
答案 1 :(得分:3)
它也可以使用默认实体和另一种实体:
<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)
替代方案。
答案 2 :(得分:1)
您可以使用配置执行此操作:
name
创建两个映射,但为它们提供不同的逻辑 entity-name
和表名字。 Session
方法,您可以将 entityName
作为参数来区分彼此。这实现了什么?
entity-type
或另一个(因此暗示一个表或另一个表)entity-type
- 尝试使用其他 entity-type
进行更新被hibernate拒绝了。否则,已修改的实体已经填充了标识符,因此hibernate将尝试更新而不是插入,但这会在数据库中失败 - 尝试更新表中从未存在的数据。费用是多少?
是否有超过子类型的好处?
你应该这样做吗?
答案 3 :(得分:0)
虽然我从未使用过,但在休眠中有一个辅助表的概念。而@SecondaryTables是hibernate中的注释,实体可以通过该注释映射多个表来获取数据。获取数据的实体应该具有@SecondaryTables注释。它基于主键和外键并且还基于唯一约束来关联辅助表。
以下是我在google上找到的一个示例,请检查它是否有助于您实现:
http://www.concretepage.com/hibernate/secondarytables_hibernate_annotation.php
答案 4 :(得分:0)
我知道这个问题是很久以前问过的。但我想提出一种替代方法,而不使用任何休眠方式。对于那些不想使用xml配置的人。
使用commun列的getter和setter方法声明一个接口,然后使两个实体类实现此接口。 照常在这两个实体类中保留映射注释,然后在您的代码中可以改为调用此接口的方法。