[英]Hibernate: Inconsistent primary key generation due to one-to-one relation
I have two one-to-one relations here between a class called "MailAccount" and the classes "IncomingServer" and "OutgoingServer". 我在一个名为“MailAccount”的类和“IncomingServer”和“OutgoingServer”类之间有两个一对一的关系。
(It's a Java application running on Tomcat and Ubuntu server edition). (它是在Tomcat和Ubuntu服务器版上运行的Java应用程序)。
The mapping looks like this: 映射看起来像这样:
MailAccount.hbm.xml MailAccount.hbm.xml
<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>
<one-to-one name="incomingServer" cascade="all-delete-orphan">
</one-to-one>
<one-to-one name="outgoingServer" cascade="all-delete-orphan">
</one-to-one>
</class>
</hibernate-mapping>
IncomingMailServer.hbm.xml IncomingMailServer.hbm.xml
<hibernate-mapping>
<class name="com.IncomingMailServer" table="MAILSERVER_INCOMING" abstract="true">
<id name="id" type="long" access="field">
<column name="MAIL_SERVER_ID" />
<generator class="native" />
</id>
<discriminator column="SERVER_TYPE" type="string"/>
<many-to-one name="mailAccount" column="MAIL_ACCOUNT_ID" not-null="true" unique="true" />
<subclass name="com.ImapServer" extends="com.IncomingMailServer" discriminator-value="IMAP_SERVER" />
<subclass name="com.Pop3Server" extends="com.IncomingMailServer" discriminator-value="POP3_SERVER" />
</class>
</hibernate-mapping>
OutgoingMailServer.hbm.xml OutgoingMailServer.hbm.xml
<hibernate-mapping>
<class name="com.OutgoingMailServer" table="MAILSERVER_OUTGOING" abstract="true">
<id name="id" type="long" access="field">
<column name="MAIL_SERVER_ID" />
<generator class="native" />
</id>
<discriminator column="SERVER_TYPE" type="string"/>
<many-to-one name="mailAccount" column="MAIL_ACCOUNT_ID" not-null="true" unique="true" />
<subclass name="com.SmtpServer" extends="com.OutgoingMailServer" discriminator-value="SMTP_SERVER" />
</class>
</hibernate-mapping>
The class hierarchy looks like this: 类层次结构如下所示:
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{
// ...
}
Now, here comes the problem : 现在, 问题出现了 :
Although most of the time my application runs well, there seems to be one situation in which email servers get deleted, but the corresponding account doesn't and that's when this call is made: 虽然大部分时间我的应用程序运行良好,但似乎有一种情况是电子邮件服务器被删除,但相应的帐户没有,而且这是在进行此调用时:
session.delete(mailAccountInstance);
In a one-to-one relation in Hibernate, the primary keys between mail account and its servers must be equal, if not, the relation completely gets out of sync: 在Hibernate中的一对一关系中,邮件帐户与其服务器之间的主键必须相等,否则,关系完全不同步:
Example: 例:
Imagine, the tables are filled with data like this: 想象一下,表格中填充了以下数据:
Table "MailAccount" (Current auto_increment value: 2) 表“MailAccount”(当前auto_increment值:2)
MAIL_ACCOUNT_ID NAME
0 Account1
1 Account2
Table "IncomingMailServer" (Current auto_increment value: 2) 表“IncomingMailServer”(当前auto_increment值:2)
MAIL_SERVER_ID MAIL_ACCOUNT_ID
0 0
1 1
Now, image the account with ID=1 gets deleted and new accounts get added. 现在,图像ID = 1的帐户被删除,新帐户被添加。 The following then SOMETIMES happens:
然后发生以下有时:
Table "MailAccount" (Current auto_increment value: 3) 表“MailAccount”(当前auto_increment值:3)
MAIL_ACCOUNT_ID NAME
0 Account1
1 Account2
2 Account3
Table "IncomingMailServer" (Current auto_increment value: 2) 表“IncomingMailServer”(当前auto_increment值:2)
MAIL_SERVER_ID MAIL_ACCOUNT_ID
0 0
1 2
This completely messes up my database consistency. 这完全扰乱了我的数据库一致性。 How can I avoid this?
我怎么能避免这个?
If you want a shared primary key, you can use the native id generator only once. 如果需要共享主键,则只能使用本机ID生成器一次。 You create the mail account first, which will generate its own id, but when you create the Incoming- or OutgoingMailServer, these need to take their id from the mailAccount property.
您首先创建邮件帐户,这将生成自己的ID,但是当您创建Incoming-或OutgoingMailServer时,这些需要从mailAccount属性中获取其ID。
So you need the "foreign" generator: 所以你需要“外来”发电机:
<class name="OutgoingMailServer">
<id name="id" column="MAIL_SERVER_ID">
<generator class="foreign">
<param name="property">mailAccount</param>
</generator>
</id>
<one-to-one name="mailAccount" not-null="true" constrained="true"/>
<class>
You don't need a MAIL_ACCOUNT_ID column, since it will always be identical to the MAIL_SERVER_ID anyway. 您不需要MAIL_ACCOUNT_ID列,因为它始终与MAIL_SERVER_ID完全相同。
Quite basic follow the reference about bidirectional one-to-one association on a primary key . 基本遵循关于主键上的双向一对一关联的参考。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.