2012-08-08 97 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