In previous tutorial, we learned about saving entities using save()
or saveOrUpdate()
methods in hibernate. There we learned that in most of the cases, you will not even need those methods as hibernate manages the updates on persistent entities automatically. You only need to care about transient objects in most of cases. In this tutorial, I am discussing few thoughts around refresh()
and merge()
method present in hibernate session class.
Refreshing Hibernate Entities Using refresh() Method
Sometimes we face situation where we application database is modified with some external application/agent and thus corresponding hibernate entity in your application actually becomes out of sync with it’s database representation i.e. having old data. In this case, you can use session.refresh()
method to re-populate the entity with latest data available in database.
You can use one of the refresh() methods on the Session interface to refresh an instance of a persistent object, as follows:
public void refresh(Object object) throws HibernateException public void refresh(Object object, LockMode lockMode) throws HibernateException
These methods will reload the properties of the object from the database, overwriting them. In real life applications, you do not have to use the refresh()
method very often apart from above stated scenario.
Let’s look at an example of refresh() method.
public class RefreshEntityExample { public static void main(String[] args) { Session sessionOne = HibernateUtil.getSessionFactory().openSession(); sessionOne.beginTransaction(); //Create new Employee object EmployeeEntity emp = new EmployeeEntity(); emp.setEmployeeId(1); emp.setFirstName("Lokesh"); emp.setLastName("Gupta"); //Save employee sessionOne.save(emp); sessionOne.getTransaction().commit(); sessionOne.close(); //Verify employee's firstname System.out.println(verifyEmployeeFirstName(1, "Lokesh")); Session sessionTwo = HibernateUtil.getSessionFactory().openSession(); sessionTwo.beginTransaction(); //This emp.setFirstName("Vikas"); sessionTwo.refresh(emp); sessionTwo.getTransaction().commit(); sessionTwo.close(); System.out.println(emp.getFirstName().equals("Lokesh")); HibernateUtil.shutdown(); } private static boolean verifyEmployeeFirstName(Integer employeeId, String firstName){ Session session = HibernateUtil.getSessionFactory().openSession(); EmployeeEntity employee = (EmployeeEntity) session.load(EmployeeEntity.class, employeeId); //Verify first name boolean result = firstName.equals(employee.getFirstName()); session.close(); //Return verification result return result; } } Output: true true
Look above the highlighted lines.
- Line 15 save the employee with first name “Lokesh”
- Line 26 set the first name “Vikas”. As entity is detached, DB will not be updated.
- Line 27 refresh the entity with database using
refresh()
method. - Line 32 verify that firstname set in entity has been updated with “Lokesh” as it is what database have this moment.
This was all about refresh method. Let’s look an another similar method merge()
.
Merging Hibernate Entities Using merge() Method
Method merge()
does exactly opposite to what refresh()
does i.e. It updates the database with values from a detached entity. Refresh method was updating the entity with latest database information. So basically, both are exactly opposite.
Merging is performed when you desire to have a detached entity changed to persistent state again, with the detached entity’s changes migrated to (or overriding) the database. The method signatures for the merge operations are:
Object merge(Object object) Object merge(String entityName, Object object)
Hibernate official documentation give a very good explanation of merge()
method:
So if I take below code for example then below listed points should be clear to you.
EmployeeEntity mergedEmpEntity = session.merge(empEntity);
- ’empEntity’ is detached entity when it is passed to merge() method.
- merge() method will search for an already loaded EmployeeEntity instance with identifier information taken from empEntity. If such persistent entity is found then it will be used for updates. Other wise a new EmployeeEntity is loaded into session using same identifier information as present in ’empEntity’.
- Data is copied from ’empEntity’ to new found/loaded entity.
- Because new/found entity is persistent, all data copied to it from ’empEntity’ is automatically saved into database.
- Reference of that new entity is returned from merge() method and is assigned to ‘mergedEmpEntity’ variable.
- ’empEntity’ is still detached entity.
public class MergeEntityExample { public static void main(String[] args) { Session sessionOne = HibernateUtil.getSessionFactory().openSession(); sessionOne.beginTransaction(); //Create new Employee object EmployeeEntity emp = new EmployeeEntity(); emp.setEmployeeId(1); emp.setFirstName("Lokesh"); emp.setLastName("Gupta"); //Save employee sessionOne.save(emp); sessionOne.getTransaction().commit(); sessionOne.close(); //Verify employee's firstname System.out.println(verifyEmployeeFirstName(1, "Lokesh")); Session sessionTwo = HibernateUtil.getSessionFactory().openSession(); sessionTwo.beginTransaction(); //Set new first name emp.setFirstName("Vikas"); //Merge the emp object using merge() method EmployeeEntity mergedPersistentEmpEntity = (EmployeeEntity) sessionTwo.merge(emp); sessionTwo.getTransaction().commit(); sessionTwo.close(); //Verify employee's firstname again in database System.out.println(verifyEmployeeFirstName(1, "Vikas")); HibernateUtil.shutdown(); } private static boolean verifyEmployeeFirstName(Integer employeeId, String firstName){ Session session = HibernateUtil.getSessionFactory().openSession(); EmployeeEntity employee = (EmployeeEntity) session.load(EmployeeEntity.class, employeeId); //Verify first name boolean result = firstName.equals(employee.getFirstName()); session.close(); //Return verification result return result; } } Output: true true
In above example, ‘mergedPersistentEmpEntity’ is new entity which is persistent. So if you want to any more change, then make in in ‘mergedPersistentEmpEntity’ instance.
That’s all for this tutorial covering merge()
and refresh()
methods in hibernate. Remember that question can be asked as difference between merge()
and refresh()
, or difference between merge()
and load()
etc. Be ready to encounter any such difference between interview questions.
Happy Learning !!
Sachin
Hi,
I think here in ur example it is updating in case of merge only since u have specified the id manually if u use auto generated id then it will insert a new record instead of updating it.
Lokesh Gupta
Please update the logic accordingly. Its only for demo purpose.
nms
Hi Kishore,
Not sure If your doubt got cleared by this time or not. I came to see your question now, have gone through your code and got some clue on what might have happened.
Actually session.get will cache the object loaded from database. so both emp1 and emp2 is cached here.
I think it has taken the cached emp2 object. looks like refresh has not loaded the updated db employee object data here since its done on emp2 and not emp1. Not sure why so . need to research on this
Thanks,
nms
Kishore Anand
Hi Lokesh,
I have a doubt. I opened two sessions in parallel and updated/committed an emp entity. However when the session2 is still open I am not able to refresh the changes made by session1 into emp persistent object. Please can you tell me what I am doing wrong here.
My code –
https://github.com/kishore5242/Hibernate/blob/a4803f66b4f9a8fdc7d0f0c8e764a2b346153976/hibernate-simple/src/main/java/com/klearn/hibernate/app/TwoSessionCacheRunner.java#L46
Any response is much appreciated. Thank you
Lokesh Gupta
Can you please try to debug the code and share your findings. Ideally, it should have refreshed.
Kishore Anand
Thank you for the quick reply. Here is more info –
Screenshots –
https://github.com/kishore5242/Hibernate/tree/master/hibernate-simple/doubts/refresh
Console output –
Hibernate: select next_val as id_val from hibernate_sequence for update
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
Hibernate: insert into EMPLOYEE (EMP_NAME, EMP_ID) values (?, ?)
Two sessions loading same Employee….
Hibernate: select employee0_.EMP_ID as EMP_ID1_0_0_, employee0_.EMP_NAME as EMP_NAME2_0_0_ from EMPLOYEE employee0_ where employee0_.EMP_ID=?
Hibernate: select employee0_.EMP_ID as EMP_ID1_0_0_, employee0_.EMP_NAME as EMP_NAME2_0_0_ from EMPLOYEE employee0_ where employee0_.EMP_ID=?
Loaded by both sessions.
Persistent entity in first session – Sandhya
Hibernate: update EMPLOYEE set EMP_NAME=? where EMP_ID=?
Persistent entity in second session – Kishore
Hibernate: select employee0_.EMP_ID as EMP_ID1_0_0_, employee0_.EMP_NAME as EMP_NAME2_0_0_ from EMPLOYEE employee0_ where employee0_.EMP_ID=?
Persistent entity in second session after refresh – Kishore
Anmol Bhatnagar
Just because you are trying to make changes in the database with two sessions parallely, so since both are open and the transaction is not committed, so the changes of both will not be reflected in each other data. This is the property of the database, you must be knowing 🙂
Saurabh
In the Example of Refresh:
You changed the name to “Vikas”and made a refresh and then checking the firstName with “Lokesh”(that returns true).
In my point of view you should check the first name with “Vikas” and it should return true at that time and should return false if checking with “Lokesh” as value is already updated after doing refresh.
Please let me know if my understanding is wrong.
Thanks
Lokesh Gupta
sessionTwo.refresh(emp);
resets the name to “Lokesh”.rajan
Is this because sessionTwo.save(emp); have not been called and latest data will have first name as “Lokesh”?
Nitesh
I think you should change your first line with
In the previous tutorial, we learned about saving entities using persist() methods in hibernate.
thanks
David Saraiva
All this tutorials are very helpful and its great that there are simple and concrete examples.
Thank you!
My only suggestion would be to review the order of the tutorials because its not sorted. For example, this tutorial refers to a previous tutorial but save/saveOrUpdate tutorial actually comes after if one follows the menu “Hibernate Tutorial” – on the top left of this page (which also does not seem to be organized).
Once more, this is only one detail and one can easily find what he wants. The content of the tutorials is amazing, and thank you for sharing 🙂
Satish Keshri
I like your tutorial,only thing i will suggest you to give previous and next button in the end of each tutorial. Because if we are going through the index in right side its not in the order.
Thanks
Lokesh Gupta
Thanks for the suggestion. I will work on it.
luvking
seems both merge and saveorupdate method is identical.
Adit Choudhary
saveOrUpdate only accepts Transient and persistent Entity.
DI
Great Document , I cannot find any real explanation anywhere else. Thanks for sharing !!
Pankaj Rana
your way of explanation is simply awesome. Now I will never forget the difference. Thanks !!
Ban Ăn Chơi
Thanks, nice explanation.