【问题标题】:How to save the correct discriminator value through Hibernate如何通过 Hibernate 保存正确的鉴别器值
【发布时间】:2011-05-03 21:46:57
【问题描述】:

我目前正在尝试使用 Hibernate 将我的 Java 类层次结构映射到我的数据库中,但我一直因以下(子)类而失败:

我有一个名为 MailAccount 的类,它有 3 个属性(参见下面的代码):

public class MailAccount{
    long id;
    IncomingMailServer  incomingServer;
    OutgoingMailServer  outgoingServer;

    public MailAccount(){
        super();
    }

    // Getter and setter omitted
}

服务器类层次结构如下所示:

MailServer.java

public abstract class MailServer {
    String password;
    String host;
    String username;
    String port;

    // Getter and setter omitted
}

IncomingMailServer.java

public abstract class IncomingMailServer extends MailServer {
}

OutgoingMailServer.java

public abstract class OutgoingMailServer extends MailServer {
}

Pop3Server.java

public class Pop3Server extends IncomingMailServer{
    public Pop3Server(){
        super();
    }
}

ImapServer.java

public class ImapServer extends IncomingMailServer{
    public ImapServer(){
        super();
    }
}

SmtpServer.java

public class SmtpServer extends OutgoingMailServer{
    public SmtpServer(){
        super();
    }
}

MailAccount.java 中的属性入站服务器和传出服务器当然只包含 Pop3Server、ImapServer(用于传入服务器)或 SmtpServer(用于传出服务器)的实例。

我使用如下映射配置:

MailAccount.hbm.xml

<hibernate-mapping package="test.account">
    <class name="MailAccount" table="MAILACCOUNTS" dynamic-update="true">

        <id name="id" column="MAIL_ACCOUNT_ID">
            <generator class="native" />
        </id>

        <one-to-one name="incomingServer" cascade="all">
        </one-to-one>
        <one-to-one name="outgoingServer" cascade="all">
        </one-to-one>
    </class>
</hibernate-mapping>

MailServer.hbm.xml

<hibernate-mapping>
    <class name="test.server.MailServer" table="MAILSERVER" abstract="true">

        <id name="id" type="long" access="field">
            <column name="MAIL_SERVER_ID" />
            <generator class="native" />
        </id>

        <discriminator column="SERVER_TYPE" type="string"/>

        <property name="password" column="PASSWORD" />
        <property name="host" column="HOST" />
        <property name="username" column="USERNAME" />
        <property name="port" column="PORT" />

        <one-to-one name="mailAccount" class="test.account.MailAccount" foreign-key="MAIL_SERVER_ID"></one-to-one>

        <subclass name="test.server.incoming.ImapServer" extends="test.server.incoming.IncomingMailServer" discriminator-value="IMAP_SERVER">
        </subclass>

        <subclass name="test.server.incoming.Pop3Server" extends="test.server.incoming.IncomingMailServer" discriminator-value="POP3_SERVER">
        </subclass>

        <subclass name="test.server.outgoing.SmtpServer" extends="test.server.outgoing.OutgoingMailServer" discriminator-value="SMTP_SERVER">
        </subclass>

        <subclass name="test.server.incoming.IncomingMailServer" extends="test.server.MailServer" abstract="true" discriminator-value="INCOMING_SERVER">
        </subclass>

        <subclass name="test.server.outgoing.OutgoingMailServer" extends="test.server.MailServer" abstract="true" discriminator-value="OUTGOING_SERVER">
        </subclass>

    </class>
</hibernate-mapping>

问题:每当我告诉 Hibernate 保存 MailAccount 的实例时,像这样:

session = getSession();
transaction = session.beginTransaction();
session.save(mailAccount);
transaction.commit();

.. Hibernate 将所有内容都正确存储,除了表 MailServer 中的鉴别器列 SERVER_TYPE。 在此列中,Hibernate 应存储“IMAP_SERVER”、“POP3_SERVER”或“SMTP_SERVER”,但它会保存“INCOMING_SERVER”或“OUTGOING_SERVER”。

当我尝试从数据库加载此实体时,(当然)会发生异常,因为 Hibernate 正在尝试实例化类型为“IncomingMailServer”或“OutgoingMailServer”的对象,它们都是抽象的。 那么,如何让 Hibernate 保存正确的类型呢?

示例:如果属性incomingServer 拥有一个Pop3Server 的实例,那么Hiberante 应该将它存储到我的数据库中,当我加载相应的MailAccount 时,我希望Hibernate 重新创建一个Pop3Server 的实例。

注意:我对 Hibernate 还很陌生,这是我使用它的第一步,所以请保持温和 :-) 。我知道我的 .hmb.xml 文件可能看起来很乱,所以如果您有改进建议,请继续 :-)

【问题讨论】:

  • 我没有使用 .hbm 文件的经验,但是为抽象类指定鉴别器值有什么意义呢?你不应该只为叶子指定这些吗?
  • 您好,感谢您的回复!当我删除&lt;subclass name="IncomingMailServer" .../&gt;&lt;subclass name="OutgoingMailServer" .../&gt; 行时,我得到以下异常:org.hibernate.MappingException: persistent class not known: test.server.incoming.IncomingMailServer。如果我只是删除属性discriminator-value="INCOMING_SERVER"discriminator-value="OUTGOING_SERVER",那么Hibernate 会将完整的类名test.server.incoming.IncomingMailServertest.server.outgoing.OutgoingMailServer 保存到鉴别器列SERVER_TYPE

标签: java hibernate


【解决方案1】:

&lt;subclass&gt; 元素的嵌套应该类似于继承层次结构:

<subclass name="test.server.incoming.IncomingMailServer" extends="test.server.MailServer" abstract="true" discriminator-value="INCOMING_SERVER">
    <subclass name="test.server.incoming.ImapServer" extends="test.server.incoming.IncomingMailServer" discriminator-value="IMAP_SERVER">
    </subclass> 
    <subclass name="test.server.incoming.Pop3Server" extends="test.server.incoming.IncomingMailServer" discriminator-value="POP3_SERVER">
    </subclass>
</subclass>

<subclass name="test.server.outgoing.OutgoingMailServer" extends="test.server.MailServer" abstract="true" discriminator-value="OUTGOING_SERVER">
    <subclass name="test.server.outgoing.SmtpServer" extends="test.server.outgoing.OutgoingMailServer" discriminator-value="SMTP_SERVER">
    </subclass>
</subclass>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多