繁体   English   中英

休眠,映射继承的字段

[英]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调整来代替注释,但是我只使用了注释。)

@MappedSuperclass批注。

如果您只想使用包含两个Java类的所有列的一个数据库表(DatabasePerson),则可以使用以下注释:

@MappedSuperclass
class Person {
    String name;
    int age;
}

@Entity
class DatabasePerson extends Person {
    int databaseId;
}

我认为在这种情况下最好将Person类更改为abstract类。


InheritanceType.SINGLE_TABLE

@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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM