Card 05/ 07

ComparisonDifficulty: Advanced1 min

refresh() vs clear() in JPA

One reloads a single entity from the database; the other stops tracking everything and reads nothing.

refresh() and clear() both sound as though they undo something, and they undo different things. refresh(entity) reloads one entity from the database, overwriting its unsaved changes. clear() detaches every entity the persistence context (JPA's record of the entities it is tracking in the current transaction) is tracking, and does not touch the database at all.

What they share is that neither one writes: refresh() only reads, and clear() does not touch the database. An unsaved change is therefore lost either way, overwritten by refresh() and abandoned by clear().

Running each one against entities in the same persistence context: first a status changed directly in the database and then refreshed, then a tracked entity before and after clear():

text
before refresh, in-memory status = open
after refresh(), in-memory status = modified-directly

before clear(), contains? true
after clear(), contains? false
run in a container: refresh() reloaded one entity; clear() detached everything without touching the database
refresh() compared with clear()
Compared onrefresh()clear()
ScopeOne entityEvery managed entity
Touches the databaseYes: runs a fresh SELECTNo
Unsaved local changesDiscarded, overwritten by the database's valuesKept in memory, but no longer tracked or saved

The decision rule. Use refresh() when the question is "has this row changed underneath me?": it brings back the current data for one entity. Use clear() to stop tracking, most often in a long batch job that would otherwise build up an ever-growing persistence context in memory; it gets you nothing from the database.