2011-09-26 21 views
4

在名爲「MailAccount」的類與「IncomingServer」和「OutgoingServer」類之間存在兩個一對一的關係。Hibernate:由於一對一關係而導致的主鍵生成不一致

(這是一個在Tomcat和Ubuntu服務器版上運行的Java應用程序)。

的映射是這樣的:

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

<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

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

的類層次結構如下所示:

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{ 
// ... 
} 

現在,這裏說到問題

雖然我的大多數應用程序運行良好的時候,似乎有一個情況哪些電子郵件服務器被刪除,但相應的帳戶不會,並且這是該電話發出時的情況:

session.delete(mailAccountInstance); 

在休眠一對一的關係,郵件帳戶和它的服務器之間的主密鑰必須是相等的,如果不是,則關係完全得到不同步:

實施例:

想象,表中填充數據是這樣的:

表 「MailAccount」(當前AUTO_INCREMENT值:2)

MAIL_ACCOUNT_ID NAME 
0    Account1 
1    Account2 

表 「IncomingMailServer」(當前auto_incremen t值:2)

MAIL_SERVER_ID MAIL_ACCOUNT_ID 
0    0 
1    1 

現在,圖像ID = 1的帳戶被刪除,新的帳戶被添加。下面接着有時會發生:

表 「MailAccount」(當前AUTO_INCREMENT值:3)

MAIL_ACCOUNT_ID NAME 
0    Account1 
1    Account2 
2    Account3 

表 「IncomingMailServer」(當前AUTO_INCREMENT值:2)

MAIL_SERVER_ID MAIL_ACCOUNT_ID 
0    0 
1    2 

這完全弄亂我的數據庫一致。 我該如何避免這種情況?

+2

如果沒有解決方案,那麼您聲明主鍵必須相同的一對一關係的部分是錯誤的。對於每個關係,MAILACCOUNTS中必須有一個匹配的表或帶有外鍵的列。 – Nicktar

+0

Nicktar部分屬實。映射中的一對一關聯是通過在IncomingMailServer中存在外鍵MAIL_ACCOUNT_ID來實現的。 MailAccount和IncomingMailServer的主鍵可能完全不同。你的問題的診斷是錯誤的。如果某些郵件服務器消失了,那是因爲您將其刪除,或者因爲某個帳戶的郵件服務器設置爲空,由於delete-orphan配置,該郵件服務器從數據庫中刪除了郵件服務器。 –

+0

@Nicktar這很奇怪。我沒有這樣的匹配表。 「外鍵」MAIL_ACCOUNT_ID與匹配沒有任何關係。如果Incoming-/OutgoingServer的主鍵不同步,則從此處的所有內容都會被徹底搞砸。關鍵的MAIL_ACCOUNT_ID仍然可以引用正確的MailAccount,但這沒有幫助。休眠只匹配PK的。 – Timo

回答

4

如果您想要共享主鍵,則只能使用本機ID生成器一次。您首先創建郵件帳戶,該郵件帳戶將生成其自己的ID,但是當您創建Incoming或OutgoingMailServer時,這些帳戶需要從mailAccount屬性中獲取其ID。

所以你需要「洋」發電機:

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

你不需要MAIL_ACCOUNT_ID列,因爲它總是會等同於MAIL_SERVER_ID反正。

完全基本遵循關於bidirectional one-to-one association on a primary key的參考。

+0

這很奇怪。當我這樣做,並調用'session.save(mailAccountInstance)',那麼我得到一個NullPointerException在'org.hibernate.tuple.entity.AbstractEntityTuplizer.getPropertyValue(AbstractEntityTuplizer。Java的:521)'。我已經檢查過被引用的郵件服務器或郵件帳戶是否可以爲空,但它們不是。以下是完整的跟蹤:http://dl.dropbox.com/u/17844821/zeug/stacktrace.txt – Timo

+0

@greyfairer幾乎是正確的,但'column =「MAIL_SERVER_ID」'屬性必須位於id標記中,不是在一對一的標籤 – Fortunato

+0

@Fortunato thx,修正了這一點。 – greyfairer

相關問題