Hibernate:复合PK与Surrogate PK的观点

据我了解,每当我在JPA / Hibernate实体内的Long字段上使用@Id和@GeneratedValue时,我实际上使用的是代理键,我认为这是一种非常好的方法来定义主键,考虑到我不是 – 使用复合主键的良好体验,其中:

  1. 有超过1个业务价值列组合成为独特的PK
  2. 复合pk值在表详细信息中重复
  3. 无法改变复合PK内部的业务价值

我知道hibernate可以支持这两种类型的PK,但我不知道我之前与经验丰富的同事聊天,他们说复合PK在执行复杂的SQL查询和存储过程进程时更容易处理。

他们继续说,当使用代理键时,在加入时会使事情变得复杂,并且在使用代理键时不可能做某些事情时有几种情况。 虽然我很抱歉我不能解释这里的细节,因为当他们解释时我还不够清楚。 也许下次我会提供更多细节。

我目前正在尝试做一个项目,并希望尝试代理键,因为它不会在表之间重复,我们可以更改业务列值。 而当需要一些商业价值组合的独特性时,我可以使用类似的东西:

@Table(name="MY_TABLE", uniqueConstraints={ @UniqueConstraint(columnNames={"FIRST_NAME", "LAST_NAME"}) // name + lastName combination must be unique 

但由于之前关于复合键的讨论,我仍然存在疑问。

你能分享一下这方面的经验吗? 谢谢 !

关于任何应用程序的第一条规则是需求发生变化。 期。 因此,今天看起来像PK的好候选人可能不会是明天的PK。

如果值包含以下特征,则值是PK的良好候选:

  1. 这是不可改变的。 它永远不会改变。
  2. 唯一性。 两条记录永远不会共享相同的ID。

也就是说,在现实世界中以永恒的方式拥有这些特征几乎是不可能的。 我的意思是,即使今天的某些东西是不可变的和独特的,但这并不意味着它总是那样。

因此,尽可能使用代理键。 仅对旧数据库使用自然键。 并且远离那些建议自然键比代理(开玩笑)更好的朋友:-)

当然:您可以在数据库中使用约束来强制执行唯一性规则(就像您在示例中所做的那样),这使得两条记录无法共享相同的值(如果这是业务规则)。 当业务逻辑在未来发生变化时,您会很高兴看到您使用了代理键;-)

但是不要相信stackoverflow上的随机花花公子。 阅读维基百科的这两篇文章:

http://en.wikipedia.org/wiki/Surrogate_key

http://en.wikipedia.org/wiki/Natural_key

Hibernate似乎鼓励使用代理键。 我更喜欢使用复合键,但不想对抗框架,并且复合键在Hibernate中使用起来很麻烦。 因此,为了充分利用两个世界,我使用代理键,但也使用@NaturalId标记我想要的复合键列,以便Hibernate为我创建独特的约束。 @NaturalId的默认可变性为false,因此如果需要更新“复合键”字段,请使用@NaturalId(mutability = true)。