HowToDoInJava

  • Python
  • Java
  • Spring Boot
  • Dark Mode
Home / Hibernate / Hibernate Merging and Refreshing Entities

Hibernate Merging and Refreshing Entities

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:

Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with cascade=”merge”.

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 !!

Share this:

  • Twitter
  • Facebook
  • LinkedIn
  • Reddit

About Lokesh Gupta

A family guy with fun loving nature. Love computers, programming and solving everyday problems. Find me on Facebook and Twitter.

Feedback, Discussion and Comments

  1. Sachin

    October 31, 2019

    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

      November 1, 2019

      Please update the logic accordingly. Its only for demo purpose.

  2. nms

    September 6, 2019

    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

  3. Kishore Anand

    August 9, 2019

    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

      August 9, 2019

      Can you please try to debug the code and share your findings. Ideally, it should have refreshed.

      • Kishore Anand

        August 10, 2019

        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

          February 8, 2020

          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 🙂

  4. Saurabh

    July 29, 2019

    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

      July 30, 2019

      sessionTwo.refresh(emp); resets the name to “Lokesh”.

      • rajan

        September 12, 2019

        Is this because sessionTwo.save(emp); have not been called and latest data will have first name as “Lokesh”?

  5. Nitesh

    June 26, 2019

    I think you should change your first line with
    In the previous tutorial, we learned about saving entities using persist() methods in hibernate.

    thanks

  6. David Saraiva

    June 14, 2019

    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 🙂

  7. Satish Keshri

    July 3, 2018

    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

      July 4, 2018

      Thanks for the suggestion. I will work on it.

  8. luvking

    March 31, 2018

    seems both merge and saveorupdate method is identical.

    • Adit Choudhary

      August 7, 2019

      saveOrUpdate only accepts Transient and persistent Entity.

  9. DI

    January 3, 2017

    Great Document , I cannot find any real explanation anywhere else. Thanks for sharing !!

  10. Pankaj Rana

    November 26, 2015

    your way of explanation is simply awesome. Now I will never forget the difference. Thanks !!

  11. Ban Ăn Chơi

    October 10, 2014

    Thanks, nice explanation.

Comments are closed on this article!

Search Tutorials

Hibernate Tutorial

  • Hibernate – Introduction
  • Hibernate – Hello World
  • Hibernate – Get/Fetch
  • Hibernate – Persist
  • Hibernate – Merge & Refresh
  • Hibernate – Get Entity Reference
  • Hibernate – BLOB
  • Hibernate – Save Update
  • Hibernate – Persistence LifeCycle
  • Hibernate – SessionFactory
  • Hibernate – Entities Equality
  • Hibernate – Cascade Types
  • Hibernate – Lazy Loading
  • Hibernate – Criteria Queries
  • Hibernate – HQL
  • Hibernate – Named Query
  • Hibernate – Mappings
  • Hibernate – First Level Cache
  • Hibernate – Second Level Cache
  • Hibernate – EhCache Configuration
  • Hibernate – OSCache Configuration
  • Hibernate – C3P0 Connection Pool
  • Hibernate – In memory Database
  • Hibernate – Bean Validation
  • Hibernate – Validator CDI
  • UnexpectedTypeException

Hibernate Annotations

  • Hibernate – JPA 2 Annotations
  • Annotations Vs Mappings
  • Hibernate – @Immutable
  • Hibernate – @NaturalId
  • Hibernate – @OneToMany
  • Hibernate – @ManyToMany
  • Hibernate – @OneToOne

Meta Links

  • About Me
  • Contact Us
  • Privacy policy
  • Advertise
  • Guest and Sponsored Posts

Recommended Reading

  • 10 Life Lessons
  • Secure Hash Algorithms
  • How Web Servers work?
  • How Java I/O Works Internally?
  • Best Way to Learn Java
  • Java Best Practices Guide
  • Microservices Tutorial
  • REST API Tutorial
  • How to Start New Blog

Copyright © 2020 · HowToDoInjava.com · All Rights Reserved. | Sitemap

  • Java 15 New Features
  • Sealed Classes and Interfaces
  • EdDSA (Ed25519 / Ed448)