Spring Data JPA: Refreshing an Entity

  • Post last modified:June 6, 2023
  • Reading time:3 mins read

Understanding Refresh in JPA with Simple Use Case

Introduction

  • One of the methods provided by JPA specification is refresh(). In this article, we will learn about the refresh method and its use case.

Refresh an Entity

  • The prime goal of the refresh method is to refresh the state of an instance from the database and overrides the state in the current persistence context so that the current copy becomes the latest.
  • But the main question is how come our entity in the persistence context become out of sync with the database record?
  • One of the use cases would be when multiple application writing to the database. Between we read the entity, updating it, and writing it back to the database, there may be some other application that updated some attribute of the database table and immediately our entity in the persistence context becomes stale.
  • Hence in such cases, it would be a good idea to refresh our entity by loading instances from the database.
  • We will see one example that demonstrates this scenario.

Use Case

Initial Record in DB

Invoking Target Process

  • Now we invoked our process that reads the above record from the database.
  • We are putting a sleep of 20 sec to depict log running logic.
  • Now we have an account entity in persistence context that we read from the database and next, we are sleeping for 20 secs.
 public void refreshEntityExample() throws InterruptedException {
        Optional<Account> optionalAccount = accountRepository.findByUsername("sam_1234");
        Thread.sleep(20000);
        if(optionalAccount.isPresent()){
            Account loadedFromDB = optionalAccount.get();
            loadedFromDB.setEmail("loadedfromdb1xasfsed32@gmail.com");
            loadedFromDB.setPassword("updated_password_1234");
        }
    }
  • Meanwhile, we are sleeping there was another process that updated the permission of the record that we have in the persistence context.
    @Transactional
    public void updateAccountEntity() {
        Account account = accountRepository.findByUsername("sam_1234").get();
        Permission editor = permissionRepository.findByType("editor");
        account.setPermission(editor);
    }
  • Now the loadedFromDB entity becomes out of sync with the database with permission type stale.
  • after coming out of sleep we updated the email & password of the stale entity and also updated the permission type back to the admin since that is what we have on our entity in the persistence context.
  • Hence in this scenario, it would be logical to use refresh() loadedFromDB entity before updating and saving it to the database.
public void refreshEntityExample() throws InterruptedException {
        Optional<Account> optionalAccount = accountRepository.findByUsername("sam_1234");
        Thread.sleep(20000);
        if(optionalAccount.isPresent()){
            Account loadedFromDB = optionalAccount.get();
            em.refresh(loadedFromDB);
            loadedFromDB.setEmail("loadedfromdb1xasfsed32@gmail.com");
            loadedFromDB.setPassword("updated_password_1234");
        }
    }

Conclusion

  • In this article, we learned about refreshing entities before issuing an update command. We also discussed potential use cases when we may use it.
  • Additionally, We can also pass LockType to the refresh method such as Optimistic or Pessimistic as the second parameter if we want to refresh with lock.

Before You Leave

Leave a Reply