Hibernate : Opinions in Composite PK vs Surrogate

2020-02-26 01:15发布

As i understand it, whenever i use @Id and @GeneratedValue on a Long field inside JPA/Hibernate entity, i'm actually using a surrogate key, and i think this is a very nice way to define a primary key considering my not-so-good experiences in using composite primary keys, where :

  1. there are more than 1 business-value-columns combination that become a unique PK
  2. the composite pk values get duplicated across the table details
  3. cannot change the business value inside that composite PK

I know hibernate can support both types of PK, but im left wondering by my previous chats with experienced colleagues where they said that composite PK is easier to deal with when doing complex SQL queries and stored procedure processes.

They went on saying that when using surrogate keys will complicate things when doing joining and there are several condition when it's impossible to do some stuffs when using surrogate keys. Although im sorry i cant explain the detail here since i was not clear enough when they explain it. Maybe i'll put more details next time.

Im currently trying to do a project, and want to try out surrogate keys, since it's not getting duplicated across tables, and we can change the business-column values. And when the need for some business value combination uniqueness, i can use something like :

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

But im still in doubt because of the previous discussion about the composite key.

Could you share your experiences in this matter ? Thank you !

2条回答
▲ chillily
2楼-- · 2020-02-26 01:51

Hibernate seems to encourage the use of surrogate keys. I prefer the use of composite keys, but don't want to fight the framework, and composite keys can get cumbersome to work with in Hibernate. So to get the best of both worlds I use a surrogate key, but also tag my would-be composite key columns with @NaturalId so that Hibernate creates the unique constraints for me. The default mutablility of @NaturalId is false, so if you need to update your "composite key" field, use @NaturalId(mutability=true).

查看更多
做自己的国王
3楼-- · 2020-02-26 02:03

The first rule about any application is that requirements change. Period. So, something which looks like a good candidate for a PK today may not be a PK at all tomorrow.

A value is a good candidate for a PK if it contains the following characteristics:

  1. It's immutable. It will never change.
  2. Uniqueness. Two records will never share the same ID.

That said, it's pretty much impossible to have anything in real world with these characteristics in a perpetual way. I mean, even if something is immutable and unique today, it doesn't means it'll always be like that.

So, go with surrogate keys whenever possible. Use natural keys only for legacy databases. And run away from those friends who suggested that natural keys are better than surrogate (kidding) :-)

And of course: you can enforce the uniqueness rule with a constraint in the database (like you did in the example), making it impossible for two records to share the same value, if that's the business rule. When the business logic changes in the future, you'll be glad to see that you used a surrogate key ;-)

But don't trust a random dude on stackoverflow for this. Read those two articles from Wikipedia:

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

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

查看更多
登录 后发表回答