hibernate/hibernate-orm · error · HibernateException
The query attempts to update an immutable entity: ${querySpa
Error message
The query attempts to update an immutable entity: ${querySpaces} (set 'hibernate.query.immutable_entity_update_query_handling_mode' to suppress) What it means
Entities mapped @Immutable (or mutable=false) must not be updated by design, and Hibernate polices bulk UPDATE statements at validation time. The setting hibernate.query.immutable_entity_update_query_handling_mode selects the reaction: WARNING logs, ALLOW logs at core level, and EXCEPTION (the default) throws HibernateException listing the entity's query spaces. Note the update also silently does nothing at runtime in some modes — the setting only controls detection messaging.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/update/SqmUpdateStatement.java:177
SqmUtil.validateCriteriaTree( this );
}
verifyUpdateTypesMatch();
}
private void verifyImmutableEntityUpdate(@Nullable String hql) {
final EntityPersister persister =
nodeBuilder().getMappingMetamodel().getEntityDescriptor( getTarget().getEntityName() );
if ( !persister.isMutable() ) {
final String querySpaces = Arrays.toString( persister.getQuerySpaces() );
switch ( nodeBuilder().getImmutableEntityUpdateQueryHandlingMode() ) {
case ALLOW :
CORE_LOGGER.immutableEntityUpdateQueryAllowed( hql, querySpaces );
break;
case WARNING:
CORE_LOGGER.immutableEntityUpdateQuery( hql, querySpaces );
break;
case EXCEPTION:
throw new HibernateException( "The query attempts to update an immutable entity: "
+ querySpaces
+ " (set '"
+ AvailableSettings.IMMUTABLE_ENTITY_UPDATE_QUERY_HANDLING_MODE
+ "' to suppress)");
}
}
}
private void verifyUpdateTypesMatch() {
final List<SqmAssignment<?>> assignments = getSetClause().getAssignments();
for ( int i = 0; i < assignments.size(); i++ ) {
final SqmAssignment<?> assignment = assignments.get( i );
final SqmPath<?> targetPath = assignment.getTargetPath();
final SqmExpression<?> expression = assignment.getValue();
assertAssignable( null, targetPath, expression, nodeBuilder() );
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Remove the update path — an immutable entity is not supposed to change; delete-and-insert instead if the data must change
- If the update is intentional and accepted, relax detection: set hibernate.query.immutable_entity_update_query_handling_mode=warning (or allow) in persistence.xml/spring.jpa.properties
- If the entity really needs mutation, remove @Immutable / set mutable=true in the mapping and re-run your concurrency tests
Example fix
# before (default EXCEPTION) # UPDATE on an @Immutable entity throws HibernateException # after — accept the update deliberately spring.jpa.properties.hibernate.query.immutable_entity_update_query_handling_mode=warning // or better: remove the update code for immutable entities
Defensive patterns
Strategy: validation
Validate before calling
// Check mutability before issuing a bulk update
EntityType<?> et = emf.getMetamodel().entity(entityName);
boolean immutable = et.getJavaType().isAnnotationPresent(org.hibernate.annotations.Immutable.class);
if (immutable) throw new UnsupportedOperationException("Refusing to update immutable entity " + entityName); Type guard
static boolean isImmutableEntity(EntityManagerFactory emf, Class<?> type) {
return type.isAnnotationPresent(org.hibernate.annotations.Immutable.class);
} Try / catch
try { em.createQuery(update).executeUpdate(); } catch (HibernateException e) { if (e.getMessage().contains("immutable entity")) { /* log config mistake and rethrow or skip */ } else throw e; } Prevention
- Grep for UPDATE paths (HQL and criteria) whenever you add @Immutable to a mapping
- Keep a list of immutable entities and check it in generic bulk-update helpers
- Decide the handling mode (warning/allow/exception) deliberately in configuration rather than relying on the default
When it happens
Trigger: Executing HQL 'UPDATE ImmutableEntity SET ...' or a CriteriaUpdate against an @Immutable entity while the handling mode is EXCEPTION (default). Also triggered by generic bulk-update helpers that sweep many entity types, some of which are immutable.
Common situations: Marking entities immutable for caching/read-model performance while legacy update code paths remain; tests that reuse production mappings with @Immutable value objects; teams enabling stricter handling modes after an audit.
Related errors
- Strict JPA query language compliance was violated: use of im
- Increment option specified for update of non-versioned entit
- User-defined version types not supported for increment optio
- Insert conflict 'do update' clause with constraint name is n
- field type not supported on Derby: " + unit
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/8bcd8781655fd451.
Report an issue: GitHub.