2012-08-08 98 views
1

當Hibernate的EntityManager啓動並驗證實體映射時,我遇到了一個問題。在我可以起草簡單的說,我有以下四類:休眠驗證錯誤的實體外鍵

@Entity 
@Table(name="abc_rule") 
public class Rule { 
    @Id 
    @Column(name="id") 
    private Integer id; 

    @ManyToOne 
    private RuleType ruleType; 
} 

@Entity 
@Table(name="abc_rule_type") 
@IdClass(RuleTypeKey.class) 
public class RuleType { 
    @Id 
    private String typeCode; 

    @Id 
    private String otherCode; 

    @Column(name="descr") 
    private String description; 
} 

public class RuleTypeKey { 
    @Id 
    @Column(name="type_cd") 
    private String typeCode; 

    @Id 
    @Column(name="other_cd") 
    private String otherCode; 
} 

@Entity 
@Table(name="abc_rule_type") 
public class RuleTypeSimple { 

    @Id 
    @Column(name="id") 
    private Integer id; 

    @Column(name="type_cd") 
    private String typeCode; 

    @Column(name="other_cd") 
    private String otherCode; 

    @Column(name="descr") 
    private String description; 
} 

當Hibernate啓動時,我得到以下異常:

外鍵(FK4AD4C4B924F958E2:abc_rule [ruleType_type_cd,ruleType_other_cd ]))必須具有相同數目的列 作爲引用的主鍵的(abc_rule_type [ID])

如果我暫時上重命名@Table註解爲"abc_rule_type_123"然後Hibernate驗證並按預期使用映射。對我來說,這看起來像Hibernate正在驗證基於表名稱的外鍵映射,而不是被引用的實際類的設置。

有沒有明顯的東西我缺少這將迫使Hibernate基於類驗證?或者讓它甚至不驗證外鍵,並相信我做對了?

作爲一個方面說明,我知道有兩個不同的標識符設置映射兩次類的好理由。在我的情況下,它導致兩個不同的代碼項目在相同的數據庫上合併。一種以只讀方式使用,因此可以避開這種不尋常的映射。不幸的是,兩個代碼庫都有相當數量的代碼包裝在他們的類的版本中,重構將是一個很大的工作,我希望現在可以避免。

回答

1

請記住,Hibernate是一個ORM工具,所以您應該嘗試遵循一些OOP規則或最佳實踐來利用它。

使用幾列作爲主鍵根本不應該完成,如果你完全被迫做(如果有人會殺了你,如果你不這樣做,或者你有一個古老的關係數據庫已經創建並且超出了你的人的範圍),那麼你應該使用帶有@EmbeddedId註釋的@Embedable Id,並且也不會使用@Id註釋註釋每一列。

下面是一個EmbeddedId例如:EmbeddedCompoundPrimaryKey Example

同時,我不知道什麼是你要創建的模型(如果你至少發佈圖表或表格腳本它將幫助),但與此更正它不應該給你更多的錯誤:

@Entity 
@Table(name="abc_rule") 
public class Rule { 
    @Id 
    @Column(name="id") 
    private Integer id; 

    @ManyToOne 
    private RuleType ruleType; 
} 

@Entity 
@Table(name="abc_rule_type") 
//@IdClass(RuleTypeKey.class) <--I don't think this is right 
public class RuleType { 
    @EmbeddedId //Add this 
    private RuleTypeKey id; //And this 
    /* Remove this 
    @Id 
    private String typeCode; 

    @Id 
    private String otherCode;*/ 

    @Column(name="descr") 
    private String description; 
} 

@Embeddable //Add this 
public class RuleTypeKey { 
    //@Id <--remove this 
    @Column(name="type_cd") 
    private String typeCode; 

    //@Id <--remove this 
    @Column(name="other_cd") 
    private String otherCode; 
} 

@Entity 
//@Table(name="abc_rule_type") <--must be different table name 
@Table(name="abc_rule_type_simple") 
public class RuleTypeSimple { 

    @Id 
    @Column(name="id") 
    private Integer id; 

    @Column(name="type_cd") //Are this two colums a reference to 
    private String typeCode; //The RuleType too?? if so the must be 
          //The same as in class Rule (ManyToOne) 

    @Column(name="other_cd") 
    private String otherCode; 

    @Column(name="descr") 
    private String description; 
} 

嘗試,讓我知道,如果它的工作原理(這可能有幾個sintax錯誤,檢查它)

+0

不幸的是,休眠期間外國投完全相同的例外使用EmbeddedId時進行密鑰驗證戰略研究。 – 2012-08-09 15:00:25

+0

請檢查編輯後的回覆,我舉了一個如何實現類的例子(儘管這有助於理解你到底想要建模什麼) – 2012-08-09 23:34:43