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