org.hibernate.InstantiationException: как указать Hibernate, какой класс использовать для создания объекта - PullRequest
0 голосов
/ 29 апреля 2011

В настоящее время я пытаюсь заменить собственную реализацию контроллера базы данных на Hibernate, и у меня возникла следующая проблема при создании соответствующего файла сопоставления.

(я очень плохо знаком с Hibernate, поэтому, пожалуйста, будьте осторожны :-) -Я прочитал всю справочную документацию по Hibernate, но у меня пока нет практического опыта.)

(все это должно представлять связь между учетными записями электронной почты и настройками их сервера).

У меня есть класс с именем MailAccount, который имеет 2 свойства (см. Код ниже):

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 (для входящегоServer) или SmtpServer (для outgoingServer).

Теперь я попытался создать файл сопоставления для MailAccount:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.account">
    <class name="MailAccount" table="MAILACCOUNTS" dynamic-update="true">

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

        <component name="incomingServer" class="test.server.incoming.IncomingMailServer">
            <property name="password" column="INCOMING_SERVER_PASSWORD" />
            <property name="host" column="INCOMING_SERVER_PASSWORD" />
            <property name="username" column="INCOMING_SERVER_PASSWORD" />
            <property name="port" column="INCOMING_SERVER_PASSWORD" />
        </component>

        <component name="outgoingServer" class="test.server.outgoing.OutgoingMailServer">
            <property name="password" column="OUTGOING_SERVER_PASSWORD" />
            <property name="host" column="OUTGOING_SERVER_PASSWORD" />
            <property name="username" column="OUTGOING_SERVER_PASSWORD" />
            <property name="port" column="OUTGOING_SERVER_PASSWORD" />
        </component>
    </class>
</hibernate-mapping>

Примечание: Поскольку я получил соотношение 1: 1 между MailAccount и IncomingMailServer, а также MailAccount и OutgoingMailServer, я хочу, чтобы все в 1 таблице было для предотвращения ненужных объединений.

Проблема: Всякий раз, когда я говорю Hibernate сохранить экземпляр MailAccount, например:

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

.. Я получаю следующее исключение:

org.hibernate.InstantiationException: Невозможно создать экземпляр абстрактного классаили интерфейс: test.server.incoming.IncomingMailServer

Это полностью имеет смысл, поскольку абстрактные классы не могут быть созданы.

Однако, здесь возникает мой вопрос : Какя могу сказать Hibernate создать экземпляр правильного класса (Pop3Server, SmtpServer, ImapServer) вместо абстрактных?

Пример: Если свойство входящийServer содержит экземпляр Pop3Server, то Hiberante должен сохранить его в моей базе данных, и когда я загружаю соответствующий MailAccount обратно, я хочу, чтобы Hibernate пересоздал экземпляр Pop3Server.

1 Ответ

4 голосов
/ 29 апреля 2011

Проблема возникает из-за того, что компонент является не автономной сущностью, а "a class whose instances are stored as an intrinsic part of an owning entity and share the identity of the entity". В терминах JPA это класс Embeddable . Эти классы обычно используются для создания объекта класса из ряда столбцов таблицы, которые обычно должны храниться как отдельные атрибуты в сущности (вы можете почти рассматривать это как группирование).

Хотя у этого подхода есть ряд преимуществ, существуют некоторые ограничения. Одно из этих ограничений заключается в том, что компонент или встраиваемый объект не может быть абстрактным классом. Причина в том, что hibernate не может связать конкретный конкретный подкласс со значением, которое вы пытаетесь сохранить или прочитать. Подумайте об этом так: сможете ли вы определить, какой экземпляр создать, только взглянув на данные столбца? Обычно это не так просто, особенно для персистентности.

Чтобы получить желаемую функциональность, вам нужно рассмотреть возможность хранения данных MailServer как отдельной сущности с собственным полем первичного ключа. Это позволяет вам управлять данными с подклассами, используя различные методы наследования, например, включая DiscriminatorColumn или отдельные таблицы (в зависимости от вашей конфигурации).

Вот несколько ссылок, которые должны помочь вам в настройке этих отображений и использовании наследования сущностей:

Надеюсь, это поможет.

http://www.vaannila.com/hibernate/hibernate-example/hibernate-example.html

Если бы вы использовали этот подход с использованием Hibernate (я лично предпочитаю конфигурации аннотаций на основе JPA), вы можете настроить MailServer как абстрактный объект, который будет определять общие сопоставления столбцов между классами и DiscriminatorColumn (если используется тот же наследование таблицы). Подклассы будут построены из этого определения, добавляя настраиваемые атрибуты по мере необходимости.

...