hibernate/hibernate-orm · error · SemanticException
Increment option specified for update of non-versioned entit
Error message
Increment option specified for update of non-versioned entity
What it means
HQL/JPA supports 'UPDATE [VERSIONED] Entity ... SET ...' where VERSIONED asks Hibernate to bump the optimistic-lock version inside the bulk update SQL. BaseSqmToSqlAstConverter.addVersionedAssignment first verifies the target entity descriptor actually has a version; if persister.isVersioned() is false it throws SemanticException('Increment option specified for update of non-versioned entity'). The query is rejected at translation time - a version increment cannot be synthesized for an entity with no @Version attribute.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/sql/spi/BaseSqmToSqlAstConverter.java:911
combinePredicates( queryNodeProcessingState.getPredicate(),
additionalRestrictions ) ),
emptyList()
);
}
finally {
popProcessingStateStack();
this.currentSqmStatement = oldSqmStatement;
this.cteContainer = oldCteContainer;
}
}
public void addVersionedAssignment(Consumer<Assignment> assignmentConsumer, SqmUpdateStatement<?> sqmStatement) {
if ( sqmStatement.isVersioned() ) {
final var persister =
getMappingMetamodel()
.findEntityDescriptor( sqmStatement.getTarget().getEntityName() );
if ( !persister.isVersioned() ) {
throw new SemanticException( "Increment option specified for update of non-versioned entity" );
}
final var versionType = persister.getVersionType();
if ( versionType instanceof UserVersionType ) {
throw new SemanticException( "User-defined version types not supported for increment option" );
}
currentClauseStack.push( Clause.SET );
final var versionMapping = persister.getVersionMapping();
final var targetColumnReferences = BasicValuedPathInterpretation.from(
(SqmBasicValuedSimplePath<?>)
SqmExpressionHelper.get( sqmStatement.getRoot(),
versionMapping.getPartName() ),
this,
jpaQueryComplianceEnabled
).getColumnReferences();
currentClauseStack.pop();
assert targetColumnReferences.size() == 1;View on GitHub (pinned to fad1729dce)
Solutions
- Add a version attribute to the entity: @Version private long version; plus a DB column (flyway/liquibase migration 'alter table person add column version bigint not null default 0')
- Drop VERSIONED from the statement: 'UPDATE Person p SET p.name = :n' (bulk updates then skip version checks, as JPA specifies)
- If optimistic checking of bulk updates is required, use a version predicate manually: '... where p.version = :v' and set version = version + 1 explicitly
Example fix
-- before UPDATE VERSIONED Person p SET p.name = :name -- after (option 1: add version to entity) @Version private long version; -- after (option 2: drop the keyword) UPDATE Person p SET p.name = :name
Defensive patterns
Strategy: validation
Validate before calling
// Verify the entity is versioned before issuing UPDATE VERSIONED
boolean versioned = em.getMetamodel().entity(Person.class)
.getSingularAttributes().stream().anyMatch(SingularAttribute::isVersion);
if (!versioned) throw new IllegalStateException("Entity has no @Version; remove VERSIONED keyword"); Type guard
static boolean isVersioned(EntityManager em, Class<?> entity) {
return em.getMetamodel().entity(entity).getSingularAttributes().stream()
.anyMatch(jakarta.persistence.metamodel.SingularAttribute::isVersion);
} Try / catch
catch (SemanticException e) { if (e.getMessage().contains("non-versioned entity")) { /* add @Version + migration, or drop VERSIONED */ } else throw e; } Prevention
- Add @Version to entities before adopting UPDATE VERSIONED
- Generate a DDL migration whenever adding a version column
- Keep one canonical bulk-update builder that checks metamodel versioning
When it happens
Trigger: HQL 'UPDATE VERSIONED Person p SET p.name = :n' when Person has no @Version field; Criteria update with versioned semantics enabled (HibernateCriteriaBuilder.update(...)+versioned) against a non-versioned entity; copying the VERSIONED keyword from another entity's working update statement.
Common situations: Enabling bulk optimistic locking on legacy entities that never had a version column; adding VERSIONED while testing and forgetting to add the @Version mapping/migration; generated update statements that always emit VERSIONED; upgrading to JPA 3.2/Hibernate 7 where UPDATE VERSIONED became standardized HQL.
Related errors
- User-defined version types not supported for increment optio
- 'generated' attribute cannot be 'insert' or 'update' for ver
- Function %s() has %d parameters, but %d arguments given
- Parameter %d of function '%s()' has type '%s', but argument
- Entity '${persister.getEntityName()}' has no version and may
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/f347f83a8d5f3ea5.
Report an issue: GitHub.