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?
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.