javaspringspring-boothibernatenaturalid

Why should I use @NaturalId?


When I am looking for @NaturalId and trying to understand what the advantages of using it is. I am reading several articles like this article.

@Entity(name = "Post")
@Table(name = "post")
@org.hibernate.annotations.Cache(
    usage = CacheConcurrencyStrategy.READ_WRITE
)
@NaturalIdCache
public class Post {
 
    @Id
    @GeneratedValue
    private Long id;
 
    private String title;
 
    @NaturalId
    @Column(nullable = false, unique = true)
    private String slug;
 
    //Getters and setters omitted for brevity
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass())
            return false;
        Post post = (Post) o;
        return Objects.equals(slug, post.slug);
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(slug);
    }
}

And when retrieving record, the following approach is used:

String slug = "high-performance-java-persistence";
 
Post post = entityManager.unwrap(Session.class)
    .bySimpleNaturalId(Post.class)
    .load(slug);

I am wondering that, what is I remove @NaturalId from the slug field and retrieve the record via bySlug method? As far as I see, @NaturalId acts as an index and may help to access the record faster I think. Is that true? Could you explain the benefits of it?


Solution

  • I think the Hibernate ORM documentation explains the use of @NaturalId pretty well:

    Natural ids represent domain model unique identifiers that have a meaning in the real world too. Even if a natural id does not make a good primary key (surrogate keys being usually preferred), it’s still useful to tell Hibernate about it.

    When you mark a field as natural id, Hibernate creates a unique constraint for it in the database (if you generate it at start up) and caching using the field as key becomes possible. You can also use @NaturalIdCache to use the second-level cache. In general, it should lead to better performance when looking for the entity using the field.