java Hibernate:复合PK与代理PK中的观点
据我所知,每当我在JPA/Hibernate实体中的长字段上使用@Id和@GeneratedValue时,我实际上是在使用代理键,考虑到我在使用复合主键方面的不太好的经验,我认为这是定义主键的一种非常好的方法,其中:
- 有1个以上的业务价值列组合成为唯一的PK
- 复合pk值在表详细信息中重复
- 无法更改该组合主键内的业务值
我知道hibernate可以支持这两种类型的PK,但我之前与经验丰富的同事聊天时,他们说复合PK在执行复杂的SQL查询和存储过程过程时更容易处理,这让我感到疑惑
他们继续说,当使用代理键时,在进行连接时会使事情复杂化,并且当使用代理键时,有几种情况是不可能执行某些操作。虽然我很抱歉我不能在这里解释细节,因为他们解释的时候我不够清楚。也许下次我会说更多的细节
我目前正在尝试做一个项目,并希望尝试代理键,因为它不会在表之间重复,我们可以更改业务列值。当需要某种业务价值组合的唯一性时,我可以使用以下方法:
@Table(name="MY_TABLE", uniqueConstraints={
@UniqueConstraint(columnNames={"FIRST_NAME", "LAST_NAME"}) // name + lastName combination must be unique
但是我仍然有疑问,因为前面讨论过复合密钥
你能分享一下你在这件事上的经验吗?谢谢大家!
# 1 楼答案
任何应用程序的第一条规则都是需求会发生变化。时期所以,今天看起来是PK的好候选人的东西明天可能根本就不是PK
如果某个值包含以下特征,则该值是PK的最佳候选值:
也就是说,在现实世界中,几乎不可能永远拥有具有这些特征的任何东西。我的意思是,即使今天有些东西是不变的和独特的,但这并不意味着它永远都是这样
所以,尽可能使用代理密钥。仅对遗留数据库使用自然密钥。远离那些认为自然键比代理键更好的朋友(开玩笑):-)
当然,您可以在数据库中使用约束强制执行唯一性规则(就像您在示例中所做的那样),使两个记录不可能共享相同的值,如果这是业务规则的话。将来当业务逻辑发生变化时,您会很高兴看到您使用了代理密钥;-)
但是不要相信stackoverflow上的一个随机的家伙。阅读维基百科上的两篇文章:
http://en.wikipedia.org/wiki/Surrogate_key
http://en.wikipedia.org/wiki/Natural_key
# 2 楼答案
Hibernate似乎鼓励使用代理键。我更喜欢使用复合键,但不想与框架对抗,在Hibernate中使用复合键会变得很麻烦。因此,为了充分利用这两个世界,我使用了一个代理键,但也用@naturaid标记了我的潜在复合键列,以便Hibernate为我创建唯一的约束。@NaturalId的默认可变性为false,因此如果需要更新“复合键”字段,请使用@NaturalId(可变性=true)