[英]Hibernate, mapping inherited fields
可以说我有以下类层次结构:
class Person {
String name;
int age;
}
class DatabasePerson extends Person {
int databaseId;
}
现在我想映射DatabasePerson,请注意,我不想告诉hibernate存在一个Person类,hibernate只应在xml或注释映射时知道DatabasePerson类。 采用上述条件的冬眠能否映射年龄和名称字段? 换句话说,我想用hibernate映射DatabasePerson类,并且hibernate不应该了解Person类。 在xml中,我会这样(伪代码):
<hibernate class="DatabasePerson">
<field name="id"/>
<field name="name"/>
<field name="age"/>
</hibernate>
这样做的原因是要保持单一责任原则。 我不想将databaseId字段放入Person类,因为person类不应该知道它是持久的。 我不想在Person类中包含任何休眠注释,因为我那里有纯粹的实体逻辑,而且我也不想导入任何与数据库相关的东西,例如休眠。 我想在DatabasePerson类中进行的所有映射,这是我想要放置其他databaseId字段,编写休眠注释(或者可能是xml,我现在不知道的地方,我想将其推迟)的地方决定)。 换句话说,我们希望将数据库相关的内容和应用程序逻辑保留在单独的类中。
编辑:我可以使用这样的东西吗:
<class name="Person" table="PERSON" discriminator-value="P">
<discriminator column="DISCRIMINATOR" type="string" />
<property name="name" />
<property name="age" />
<subclass name="DatabasePerson" extends="Person" >
<id name="databaseId" column="ID">
<generator class="native" />
</id>
</subclass>
</class>
请注意,数据库ID在此xml的DatabasePerson范围内。
编辑:此xml映射是否分别对应于注释“映射的超类”? 我想我倾向于使用xml而不是注释,所以我的问题是如何在xml中使用@MappedSuperclass:
<class name="Person" table="PERSON" discriminator-value="P">
<id name="databaseId" column="PERSON_ID">
<generator class="native" />
</id>
<discriminator column="DISCRIMINATOR" type="string" />
<subclass name="DatabasePerson" extends="Person" discriminator-value="E">
<property name="name" column="name" />
<property name="age" type="int" column="age" />
</subclass>
</class>
我认为您可以使用MappedSupperclass批注或singel表继承策略仅在数据库中使用一个表。 两种情况下,JPA / Hibernate都知道Person类,但是它没有为该类创建表。 (当然,您可以使用XML调整来代替注释,但是我只使用了注释。)
如果您只想使用包含两个Java类的所有列的一个数据库表(DatabasePerson),则可以使用以下注释:
@MappedSuperclass
class Person {
String name;
int age;
}
@Entity
class DatabasePerson extends Person {
int databaseId;
}
我认为在这种情况下最好将Person类更改为abstract类。
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="yourtype",
discriminatorType=DiscriminatorType.STRING
)
class DatabasePerson{
int databaseId;
}
@Entity
@DiscriminatorValue("P")
class Person extends DatabasePerson{
String name;
int age;
}
此策略使用区分符列,仅保留一个表。
试试吧
<hibernate-mapping package="Yourpackage">
<class name="Person" table="PERSON" >
<id name="databaseId" column="ID">
<generator class="native" />
</id>
<discriminator column="DISCRIMINATOR" type="string" />
<property name="name" />
<property name="age" />
<subclass name="DatabasePerson" extends="Person" >
<property name="databaseId" column="database_Id" />
</subclass>
</class>
</hibernate-mapping>
可能是同一示例
http://viralpatel.net/blogs/hibernate-inheritence-table-per-hierarchy-mapping/
Hibernate XML配置可以完美地处理它,在我从事的项目之一中,我已经广泛使用了它。 我的情况如下,听起来可能不同,但与您的情况相同。
class Entity {
private int _id;
public int getId() { return _id; }
public void setId(int id) { _id = id; }
}
class User extends Entity {
private String _email;
public String getEmail() { return _email; }
public void setEmail(String email) { _email = email; }
}
我的意图是让User(以及我所有其他实体)继承id,因为您试图让DatabasePerson继承Person.name和age。
然后,在为用户配置映射时,我编写了以下XML文件。
<hibernate-mapping>
<class name="User" table="User">
<id name="id" type="int" column="id">
<generator class="identity"/>
</id>
<property name="email" type="string">
<column name="email" sql-type="varchar(255)"/>
</property>
.....
</class>
</hibernate-mapping>
如您所见,上述XML文件中没有任何对Entity的单独引用,在您的情况下,它转换为:XML文件仅处理DatabasePerson,因为Person根本不存在; Hibernate将使用Java自省功能从Entity检索ID,以您的情况为Person.name。
我唯一不确定的是您的Person.name和Person.age字段是否可以保留为受保护或应提升为公开。 无论哪种方式,您都可以将它们保留为受保护状态,并(最终)提供方法DatabasePerson.getName()和DatabasePerson.setName()(无需在Person级别提供这些getter / setter)。
作为附带说明,在其他答案中,建议您使用休眠的“子类”或“ MappedSuperclass”。 这些不是必需的,在您的情况下它们的用法在语义上甚至是错误的:当您具有扩展另一个DB实体的DB实体时,应该使用它们,但是在您的情况下,DatabasePerson是扩展POJO类(Person)的DB实体。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.