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 注释重命名为RuleTypeSimple"abc_rule_type_123"那么 Hibernate 将按预期验证并使用映射。在我看来,Hibernate 是根据表名而不是根据被引用的实际类的设置来验证外键映射。

我在这里遗漏了什么明显的东西会迫使 Hibernate 基于类进行验证吗?或者让它甚至不验证外键,只相信我做对了?

作为旁注,我知道没有充分的理由让类使用两个不同的标识符设置映射两次。在我的情况下,它导致了两个不同项目的代码合并在同一个数据库上。一个以只读方式使用,因此可以摆脱这种不寻常的映射。不幸的是,这两个代码库都有大量的代码围绕着他们的类版本,重构将是一项艰巨的任务,我希望暂时可以避免。

4

1 回答 1

1

请记住,Hibernate 是一个 ORM 工具,因此,您应该尝试通过遵循一些 OOP 规则或最佳实践来利用它。

根本不应该使用多列作为主键,并且如果您完全被迫这样做(例如,如果您不这样做,或者您已经创建了一个古老的关系数据库并且在您的人类之外,那么有人会杀了您)限制),那么您应该使用带有 @EmbeddedId 注释的 @Embedable Id 并且不要使用 @Id 注释来注释每一列

这是一个 EmbeddedId 示例:EmbeddedCompoundPrimaryKey 示例

同时,我不确定您打算创建的模型是什么(如果您至少发布图表或表格脚本会有所帮助),但通过这些更正,它不应该给您带来更多错误:

@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 错误,检查一下)

于 2012-08-08T18:56:50.607 回答