问题 JPA / Hibernate“Composite-id类不会覆盖equals()”


我正在使用JPA并收到以下警告。我研究了这个,并理解为什么我需要覆盖它以及Hibernate如何使用这些方法。我仍然有一个问题:

例外:

Composite-id类不会覆盖equals()

题:

为什么Hibernate只关心没有复合ID的类?它默认情况下比较 @Id 字段,如果只有一个存在,或者是否有更复杂的东西在这里?


12427
2018-03-25 21:18


起源



答案:


因为当实体没有复合ID时,它们只有一个基本支持类型(Integer,Long,String等),并且这些类已经定义明确 equals() (和 hashCode()) 方法。


11
2018-03-25 21:57



那么,我是否需要创建一个主键类,或者是否可以在类中有2个@Id标量字段并在那里覆盖等于? - John Humphreys - w00te
你应该避免使用复合键。这就是你应该做的。如果你真的不能,因为你的目标是一个无法改变的现有架构,那么你应该定义一个PK类,是的。 - JB Nizet
很感谢,我会接受这个。但无论如何最后一个问题......你如何在一个正常的多对多非规范化场景中避免它们,你需要一个只包含2个外键的表?您可以让第三个自动生成的密钥作为主键,但随后该密钥在不同的数据中心中会有所不同,这会造成麻烦并使调试变得非常复杂。 - John Humphreys - w00te
如果两个表之间存在多对多关联,则使用连接表,则实体之间应该具有ManyToMany关联。无需映射连接表。该协会处理它。阅读文档。 - JB Nizet
哎呀,你是对的。我已经在使用连接表,我刚开始工作之前就创建了每个数据库实体。事实证明,报告错误的实体甚至没有在Java代码中的任何地方使用过。谢啦。 - John Humphreys - w00te


答案:


因为当实体没有复合ID时,它们只有一个基本支持类型(Integer,Long,String等),并且这些类已经定义明确 equals() (和 hashCode()) 方法。


11
2018-03-25 21:57



那么,我是否需要创建一个主键类,或者是否可以在类中有2个@Id标量字段并在那里覆盖等于? - John Humphreys - w00te
你应该避免使用复合键。这就是你应该做的。如果你真的不能,因为你的目标是一个无法改变的现有架构,那么你应该定义一个PK类,是的。 - JB Nizet
很感谢,我会接受这个。但无论如何最后一个问题......你如何在一个正常的多对多非规范化场景中避免它们,你需要一个只包含2个外键的表?您可以让第三个自动生成的密钥作为主键,但随后该密钥在不同的数据中心中会有所不同,这会造成麻烦并使调试变得非常复杂。 - John Humphreys - w00te
如果两个表之间存在多对多关联,则使用连接表,则实体之间应该具有ManyToMany关联。无需映射连接表。该协会处理它。阅读文档。 - JB Nizet
哎呀,你是对的。我已经在使用连接表,我刚开始工作之前就创建了每个数据库实体。事实证明,报告错误的实体甚至没有在Java代码中的任何地方使用过。谢啦。 - John Humphreys - w00te


使用复合键时使用JPA,您应该使用任何一个 IdClass 要么 EmbeddedId 使用它们中的任何一个,你需要创建一个自己的类作为复合键,以便能够使用这个复合键来比较对象,这是几个操作所需要的。 EntityManager 关键类必须覆盖 equals 和 hashCode

取决于规格:

复合主键必须对应于单个持久字段或属性,或者对应于下面描述的一组此类字段或属性。必须定义主键类以表示复合主键。当数据库密钥由多个列组成时,通常在从旧数据库映射时出现复合主键。该 EmbeddedId 要么 IdClass 注释用于表示复合主键。

当使用复合主键时必须遵循。

  1. 主键类必须是公共的,并且必须具有公共的无参数构造函数。
  2. 主键类必须是可序列化的。
  3. 主键类必须定义 equals 和 hashCode 方法。这些方法的值相等的语义必须与键映射到的数据库类型的数据库相等性一致。

1
2018-03-25 21:58



那么,我不能拥有一个包含多个@Id列的类,只是在那里覆盖等号? - John Humphreys - w00te