Question 15 · Section 16

What Does the refresh() Method Do

The refresh() method reloads an entity from the database, replacing current in-memory values with actual data from the DB. This is useful when working with triggers, concurrent...

Language versions: English Russian Ukrainian

Overview

The refresh() method reloads an entity from the database, replacing current in-memory values with actual data from the DB. This is useful when working with triggers, concurrent updates, and when data freshness must be guaranteed.


Junior Level

What Does refresh() Do

refresh() - reloads an entity from the database, replacing current in-memory values.

User user = entityManager.find(User.class, 1L);
user.setName("Changed in memory");  // changed in memory

// Another transaction changed the DB
// Or a trigger changed the data

entityManager.refresh(user);  // reload from DB
// Now user has actual values from DB
// "Changed in memory" - overwritten

When to Use

  1. After triggers - database changed fields via trigger
  2. During concurrent updates - another transaction updated data
  3. To get actual data - when there’s doubt about freshness

refresh vs detach

refresh() - update data from DB (entity remains managed)
detach()  - detach entity (without DB update)

Example

@Transactional
public void updateUser(User user) {
    entityManager.persist(user);
    // Trigger in DB set created_at
    entityManager.refresh(user);
    // Now user.getCreatedAt() contains value from DB
}

Middle Level

Detailed Usage

// After trigger
User user = new User();
user.setName("John");
entityManager.persist(user);
// flush -> trigger in DB set created_at
entityManager.flush();
entityManager.refresh(user);  // get created_at from DB

// During concurrent updates
User user = entityManager.find(User.class, 1L);
// Another transaction updated user
entityManager.refresh(user);  // synchronize with DB

refresh with LockMode

// OPTIMISTIC - version check
entityManager.refresh(user, LockModeType.OPTIMISTIC);

// PESSIMISTIC_READ - read lock
entityManager.refresh(user, LockModeType.PESSIMISTIC_READ);

// PESSIMISTIC_WRITE - write lock
entityManager.refresh(user, LockModeType.PESSIMISTIC_WRITE);

// With timeout
Map<String, Object> properties = Map.of(
    "jakarta.persistence.lock.timeout", 5000
);
entityManager.refresh(user, LockModeType.PESSIMISTIC_WRITE, properties);

Common Mistakes

// refresh without reason
User user = entityManager.find(User.class, 1L);
entityManager.refresh(user);  // unnecessary SELECT!

// refresh for detached
User detached = getDetachedUser();
entityManager.refresh(detached);  // IllegalArgumentException

// refresh only for managed
User managed = entityManager.find(User.class, 1L);
entityManager.refresh(managed);  // correct

When refresh is NOT Needed

// Not needed after persist if there are no triggers/generated columns in DB. If trigger sets fields - refresh is needed (see Junior example).
User user = new User();
entityManager.persist(user);
entityManager.refresh(user);  // data is the same

// Not needed after merge
User managed = entityManager.merge(detached);
entityManager.refresh(managed);  // data is already actual

// Needed after triggers
entityManager.persist(user);
entityManager.flush();
entityManager.refresh(user);  // trigger may have changed data

Senior Level

Internal Implementation

refresh():
1. Check that entity is managed (not detached)
2. Execute SELECT * FROM table WHERE id = ?
3. Update all entity fields from result
4. Update snapshot in persistence context
5. Update EntityEntry

If LockMode specified:
- Add LOCK clause to SELECT
- Check version for OPTIMISTIC

refresh and ID Generation

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(insertable = false, updatable = false)
    private LocalDateTime createdAt;  // set by trigger
}

User user = new User();
entityManager.persist(user);
entityManager.flush();
entityManager.refresh(user);  // get createdAt from DB

refresh and Lazy Loading

User user = entityManager.find(User.class, 1L);
user.getOrders().size();  // load collection

// Another transaction changed the collection
entityManager.refresh(user);  // reload EVERYTHING including collections

// Or only collections
entityManager.refresh(user, Map.of(
    "org.hibernate.refreshMode", RefreshMode.FETCH
));
// (Available in Hibernate 6+)

Advanced Patterns

// Pattern: refresh after bulk update
@Modifying
@Query("UPDATE User u SET u.status = :status WHERE u.age > :age")
int bulkUpdate(@Param("status") String status, @Param("age") int age);

// After bulk update - refresh affected entities
User user = entityManager.find(User.class, userId);
entityManager.refresh(user);  // get actual data

Best Practices

refresh() after DB triggers
refresh() during concurrent changes
With LockMode when locking needed
flush() before refresh for synchronization

refresh() without reason (unnecessary SELECT)
refresh() for detached entities
refresh() instead of dirty checking
refresh() after persist/merge without necessity

Interview Cheat Sheet

Must know:

  • refresh() reloads an entity from DB, replacing current values
  • Used after triggers, during concurrent updates, for data freshness
  • Supports LockMode: OPTIMISTIC, PESSIMISTIC_READ, PESSIMISTIC_WRITE
  • Works only for managed entities, for detached - IllegalArgumentException
  • In Hibernate 6+ there’s RefreshMode.FETCH for loading only collections

Frequent follow-up questions:

  • When is refresh() needed? After DB triggers, during concurrent changes, after bulk update
  • refresh vs detach? refresh - updates data from DB (remains managed), detach - detaches (without update)
  • Why is refresh after persist useless? Data hasn’t changed, unnecessary SELECT
  • Can refresh have a timeout? Yes, via properties: jakarta.persistence.lock.timeout

Red flags (DO NOT say):

  • “refresh() after every persist” - unnecessary SELECT, same data
  • “refresh() for detached” - IllegalArgumentException
  • “refresh() instead of dirty checking” - dirty checking is automatic, refresh is forced
  • “I don’t understand when refresh is needed” - only triggers, concurrent changes, bulk update

Related topics:

  • [[8. What Are the Transient, Persistent, Detached, Removed States]]
  • [[14. What is the Difference Between persist() and merge()]]
  • [[17. How to Implement Optimistic Locking in JPA]]
  • [[18. How to Implement Pessimistic Locking in JPA]]