hibernate/hibernate-orm · error · DetachedObjectException

Given entity is not associated with the persistence context

Error message

Given entity is not associated with the persistence context

What it means

DetachedObjectException thrown from DefaultRefreshEventListener.refresh when persistenceContext.getEntry(object) returns null: the object passed to session.refresh() has no EntityEntry in the current session, meaning it is detached (belongs to a closed/cleared session) or transient (never persisted). refresh() re-reads database state into the managed instance, so it only works for entities attached to this session's persistence context.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/event/internal/DefaultRefreshEventListener.java:133

		}
		else if ( isTransient ) {
			return source.getEntityPersister( source.guessEntityName( object ), object );
		}
		else {
			return source.getPersistenceContextInternal().getEntry( object ).getPersister();
		}
	}

	private static void refresh(
			@Nonnull RefreshEvent event,
			@Nonnull RefreshContext refreshedAlready,
			@Nonnull Object object) {
		final var source = event.getSession();
		final var persistenceContext = source.getPersistenceContextInternal();
		final var entry = persistenceContext.getEntry( object );

		if ( entry == null ) {
			throw new DetachedObjectException( "Given entity is not associated with the persistence context" );
		}

		final var persister = entry.getPersister();
		final Object id = entry.getId();

		if ( EVENT_LISTENER_LOGGER.isTraceEnabled() ) {
			EVENT_LISTENER_LOGGER.refreshing(
					infoString( persister, id, event.getFactory() ) );
		}
		if ( !entry.isExistsInDatabase() ) {
			throw new UnresolvableObjectException( id, persister.getEntityName() );
		}

		// cascade the refresh prior to refreshing this entity
		Cascade.cascade(
				CascadingActions.REFRESH,
				CascadePoint.BEFORE_REFRESH,
				source,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Perform refresh() inside the same session/transaction that loaded the entity
  2. Reattach before refreshing: use session.merge(entity) and refresh the returned managed copy, or session.lock(entity, LockMode.NONE) when the detached state is known-unchanged
  3. Guard with session.contains(entity) — if false, reload via session.find(Entity.class, id) instead of refresh

Example fix

// before
// entity loaded in an earlier, closed session
session.refresh(order); // DetachedObjectException

// after
Order managed = session.merge(order); // reattach (returns managed copy)
session.refresh(managed);
Defensive patterns

Strategy: validation

Validate before calling

if (session.contains(order)) {
    session.refresh(order);
}
else {
    order = session.merge(order); // or session.find(Order.class, id)
    session.refresh(order);
}

Type guard

boolean isManaged(Session s, Object entity) {
    return s.contains(entity);
}

Try / catch

try {
    session.refresh(order);
} catch (DetachedObjectException e) {
    Order managed = (Order) session.merge(order);
    session.refresh(managed);
}

Prevention

When it happens

Trigger: session.refresh(detachedEntity) after the originating session was closed or after session.clear()/evict(); refreshing an entity loaded by a different SessionFactory/session instance; refreshing a newly constructed (transient) object; long-lived HTTP-session objects refreshed in a new request's session.

Common situations: Entities held past the end of a transaction in web apps (broken Open Session in View or entities stored in HTTP session / DTO caches); multi-request conversations without proper reattachment; unit tests that load entities in one session and refresh in another; Spring @Transactional boundaries between load and refresh.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/7b735197873fa569. Report an issue: GitHub.