I have the following class hierachy:
public class MailAccount{
IncomingMailServer incomingServer;
OutgoingMailServer outgoingServer;
}
public class MailServer{
HostAddress hostAddress;
Port port;
}
public class IncomingMailServer extends MailServer{
// ...
}
public class OutgoingMailServer extends MailServer{
// ...
}
public class ImapServer extends IncomingMailServer{
// ...
}
public class Pop3Server extends IncomingMailServer{
// ...
}
public class SmtpServer extends OutgoingMailServer{
// ...
}
My (simplified) mapping file looks like this:
<?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="com.mail.account">
<class name="MailAccount" table="MAILACCOUNTS" dynamic-update="true">
<id name="id" column="MAIL_ACCOUNT_ID">
<generator class="native" />
</id>
<component name="incomingServer">
<component name="hostAddress">
<property name="address" column="IS_HOST_ADDRESS"></property>
</component>
<component name="port">
<property name="portNumber" column="IS_PORT_NUMBER"></property>
</component>
</component>
<component name="outgoingServer">
<component name="hostAddress">
<property name="address" column="OS_HOST_ADDRESS"></property>
</component>
<component name="port">
<property name="portNumber" column="OS_PORT_NUMBER"></property>
</component>
</component>
</class>
</hibernate-mapping>
The problem: Hibernate throws this exception when I call session.save(mailAccountInstance);
:
org.hibernate.InstantiationException: Cannot instantiate abstract class or interface: IncomingMailServer
So, I added the following lines to the incomingServer component:
<discriminator column="SERVER_TYPE" type="string"/>
<subclass name="ImapServer" extends="IncomingMailServer" discriminator-value="IMAP_SERVER" />
<subclass name="Pop3Server" extends="IncomingMailServer" discriminator-value="POP3_SERVER" />
And to the outgoing server:
<discriminator column="SERVER_TYPE" type="string"/>
<subclass name="SmtpServer" extends="OutgoingMailServer" discriminator-value="SMTP_SERVER" />
But now, Hibernate gives me this error message:
org.xml.sax.SAXParseException: The content of element type "component" must match "(meta*,tuplizer*,parent?,(property|many-to-one|one-to-one|component|dynamic-component|any|map|set|list|bag|array|primitive-array)*)".
Obviously, Hibernate does not like these tags in components.
How could I work around this?
Ps: I already tried moving IncomingServer and OutgoingServer each to their own tables and map them via a one-to-one. That works but leads to inconsistencies in the database because I noticed that MailAccount and IncomingServer/OutgoingServer must always have the same primary key id. If not, everything gets out of sync and the autoincrement value for the primary keys don't match any more (between Mailaccount and Servers).