hibernate/hibernate-orm · error · HibernateException

Cannot force version increment relative to subtype; use the

Error message

Cannot force version increment relative to subtype; use the root type

What it means

UpdateCoordinatorStandard.forceVersionIncrement(id, currentVersion, nextVersion, session) executes the dedicated version-update mutation group. For subtype persisters of a JOINED hierarchy that group is null, because the version column lives in the root table, so the coordinator refuses with HibernateException 'Cannot force version increment relative to subtype; use the root type'. The increment must be routed through the root persister, which owns the version column.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java:137

		return versionUpdateGroup;
	}

	protected BatchKey getBatchKey() {
		return batchKey;
	}

	public final boolean isModifiableEntity(EntityEntry entry) {
		return entry == null ? entityPersister().isMutable() : entry.isModifiableEntity();
	}

	@Override
	public void forceVersionIncrement(
			Object id,
			Object currentVersion,
			Object nextVersion,
			SharedSessionContractImplementor session) {
		if ( versionUpdateGroup == null ) {
			throw new HibernateException( "Cannot force version increment relative to subtype; use the root type" );
		}
		doVersionUpdate( null, id, nextVersion, currentVersion, getLoadedState( id, session ), session );
	}

	private @Nullable Object[] getLoadedState(Object id, SharedSessionContractImplementor session) {
		return entityPersister.hasPartitionedSelectionMapping()
				? session.getPersistenceContextInternal()
				.getEntityHolder( session.generateEntityKey( id, entityPersister ) ).getEntityEntry().getLoadedState()
				: null;
	}

	@Override
	public void forceVersionIncrement(
			Object id,
			Object currentVersion,
			Object nextVersion,
			boolean batching,
			SharedSessionContractImplementor session) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Force the increment through the root type: operate on the root persister / load and lock the row as the root entity
  2. Use a bulk versioned JPQL update on the root table (UPDATE Root SET version = version + 1 WHERE id = :id)
  3. Upgrade Hibernate - JoinedSubclassEntityPersister delegates forceVersionIncrement to the super mapping type; ensure your version includes that delegation
  4. Guard call sites so force-increment is only issued when the persister is the root mapping type

Example fix

// before: force-increment reaches the subtype persister
session.buildLockRequest(LockOptions.forceVersion()).lock(customer); // Customer extends Person (JOINED)

// after: go through the root type
session.buildLockRequest(LockOptions.forceVersion()).lock(personRoot); // lock as Person
// or via bulk update on the root table:
// session.createQuery("update Person p set p.version = p.version + 1 where p.id = :id")
Defensive patterns

Strategy: validation

Validate before calling

// only force-increment through root persisters
EntityPersister p = session.getEntityPersister(entity.getClass().getName(), entity);
if (p.getSuperMappingType() != null) {
    // subtype of a JOINED hierarchy: increment via the root type or a bulk update instead
}

Try / catch

try { session.buildLockRequest(LockOptions.forceVersion()).lock(entity); } catch (HibernateException e) { if (e.getMessage().contains("relative to subtype")) { /* re-issue the lock through the root entity type */ } throw e; }

Prevention

When it happens

Trigger: session.buildLockRequest(LockOptions.forceVersion()).lock(entity) or EntityManager.lock(entity, LockModeType.OPTIMISTIC_FORCE_INCREMENT) where the instance's entity name resolves to a joined subclass rather than the hierarchy root; force-increment paths that reach the subtype's update coordinator directly instead of delegating upward.

Common situations: Version columns defined on the root of JOINED hierarchies; framework code that auto-force-increments versions on change (audit hooks, Spring lock utilities) and receives subtype instances; upgrades where delegation order in JoinedSubclassEntityPersister changed.

Related errors


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