Hibernate 4 has bring lots of improvements and @NaturalId is one of such nice improvements. As you know @Id annotation is used as meta data for specifying the primary key of an entity. But sometimes, entity is usually used in DAO layer code with id which not not primary key but its logical or natural id. In such cases, @NaturalId annotation will prove good replacement of named queries in hibernate.
For example, in any application there can be an employee entity. In this case, primary key will definitely be “employee id” but in cases such as login by email, user will provide email and password. In this case, in stead of writing named query, you can directly use @NaturalId annotation on “email” field.
How it works
If you look at logs then you will know that when you get an entity by its natural id then
- First primary key of entity is found by executing where clause of natural id
- This primary key is used fetch the information of entity
Example Usage
Let’s take this example.
For reference, latest hibernate maven dependency is as follows:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.0.Beta3</version> </dependency>
Now, a minimum employee entity will look like this:
EmployeeEntity.java
@Entity @Table(name = "Employee", uniqueConstraints = { @UniqueConstraint(columnNames = "ID"), @UniqueConstraint(columnNames = "EMAIL") }) public class EmployeeEntity implements Serializable { private static final long serialVersionUID = -1798070786993154676L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ID", unique = true, nullable = false) private Integer employeeId; //Use the natural id annotation here @NaturalId (mutable = false) @Column(name = "EMAIL", unique = true, nullable = false, length = 100) private String email; @Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100) private String firstName; @Column(name = "LAST_NAME", unique = false, nullable = false, length = 100) private String lastName; //Setters and Getters }
Now, lets see how to use this in code:
TestHibernate.java
public class TestHibernate { public static void main(String[] args) { Session session = HibernateUtil.getSessionFactory().openSession(); session.beginTransaction(); //Add new Employee object EmployeeEntity emp = new EmployeeEntity(); emp.setEmail("demo-user@mail.com"); emp.setFirstName("demo"); emp.setLastName("user"); //Save entity session.save(emp); EmployeeEntity empGet = (EmployeeEntity) session.bySimpleNaturalId( EmployeeEntity.class ).load( "demo-user@mail.com" ); System.out.println(empGet.getFirstName()); System.out.println(empGet.getLastName()); session.getTransaction().commit(); HibernateUtil.shutdown(); } } Output in console: Hibernate: insert into Employee (EMAIL, FIRST_NAME, LAST_NAME) values (?, ?, ?) Hibernate: select employeeen_.ID as ID1_0_ from Employee employeeen_ where employeeen_.EMAIL=? Hibernate: select employeeen0_.ID as ID1_0_0_, employeeen0_.EMAIL as EMAIL2_0_0_, employeeen0_.FIRST_NAME as FIRST3_0_0_, employeeen0_.LAST_NAME as LAST4_0_0_ from Employee employeeen0_ where employeeen0_.ID=? demo user
To download the source code of above tutorial, please click on below download link.
Sourcecode Download
Happy Learning !!
Mani
If we use @naturalId, then Hibernate will fire two queries, which in turn increase load on DB, So I think, it is not an improvement just a burden.
P.s. If I am wrong please correct me with good explanation.
Lokesh Gupta
In a sense, you are right. But is you have strong usecase to have logical id, its useful.
Neo89
I got some brief idea about @NaturalId by read this arctical.
Thanks about this artical.
Lokesh Gupta
A much better feeling you will get after reading this tutorial, I bet.
https://howtodoinjava.com/hibernate/immutable-and-naturalid-hibernate-specific-annotations/
Maxi
What about HibernateUtil?!?!
satish
could you plz explain more clearly about naturalId and i am new to Hibernate?