Primary Keys and ID Generation
Primary Keys and ID Generation
The primary key identifies each row, and JPA crosses it with your Java identity. Choose the key strategy carefully: the most common approach uses a database-generated identity, but distributed systems and legacy schemas demand alternatives.
Identity generation
GenerationType.IDENTITY delegates to the database's auto-increment column. It is simple and works everywhere, but the insert must happen before the id is known, which can complicate batching.
Sequence generation
GenerationType.SEQUENCE fetches the next value from a database sequence before insert. It supports efficient insert batching because ids are known beforehand. Hibernate uses a pooled sequence optimizer by default, so reserve this for tables where performance under heavy writes matters.
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "post_seq")
@SequenceGenerator(name = "post_seq", allocationSize = 50)
private Long id;
}
Natural keys and UUIDs
Sometimes a business field such as an email or a slug is the key. Use @NaturalId for immutable natural keys on top of a surrogate id. For distributed identifiers that must be globally unique, a UUID column of type char(36) is a solid choice.
Identifier best practices
Surrogate numeric ids are cheap and stable and should never change. Never use mutable natural keys as the @Id unless the business guarantees immutability, and always use Long or a wrapper type so a null id clearly signals an unsaved entity.
Key Points
- Identity generation delegates to auto-increment columns.
- Sequences support batching and are preferred under heavy writes.
- Use UUIDs when ids must be globally unique.
- Treat natural business keys with
@NaturalId, not@Id. - Wrapper types make an unsaved state explicit.