hibernate/hibernate-orm · error · HibernateException

Lock mode {} not valid for locking via 'update' statement

Error message

Lock mode {} not valid for locking via 'update' statement

What it means

UpdateLockingStrategy is the concrete dialect-facing strategy that emulates locking with an SQL UPDATE; besides the base-class check (>= PESSIMISTIC_READ) it enforces an even higher bar: LockMode must be at least LockMode.WRITE, otherwise HibernateException 'Lock mode <mode> not valid for locking via 'update' statement'. The class comment notes read-locks are not valid for this strategy. The check runs in the constructor, so it fails as soon as the dialect builds the strategy.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/lock/UpdateLockingStrategy.java:38

 * @author Steve Ebersole
 * @since 3.2
 *
 * @deprecated No longer used
 */
@Deprecated(since = "7.2", forRemoval = true)
public class UpdateLockingStrategy extends AbstractPessimisticUpdateLockingStrategy {

	/**
	 * Construct a locking strategy based on SQL UPDATE statements.
	 *
	 * @param lockable The metadata for the entity to be locked.
	 * @param lockMode Indicates the type of lock to be acquired.  Note that
	 * read-locks are not valid for this strategy.
	 */
	public UpdateLockingStrategy(EntityPersister lockable, LockMode lockMode) {
		super( lockable, lockMode );
		if ( lockMode.lessThan( LockMode.WRITE ) ) {
			throw new HibernateException( "Lock mode " + lockMode + " not valid for locking via 'update' statement" );
		}
	}

	@Override
	public void lock(Object id, Object version, Object object, int timeout, SharedSessionContractImplementor session)
			throws StaleObjectStateException, JDBCException {
		doLock( id, version, session );
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Request PESSIMISTIC_WRITE or stronger when the dialect locks via UPDATE
  2. In custom dialects, return this strategy only for WRITE-and-above modes and use a select-based strategy for PESSIMISTIC_READ
  3. Replace legacy LockMode.UPGRADE/READ constants with PESSIMISTIC_WRITE where update locking is in play

Example fix

// before
session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_READ)).lock(item);

// after
session.buildLockRequest(new LockOptions(LockMode.PESSIMISTIC_WRITE)).lock(item);
Defensive patterns

Strategy: validation

Validate before calling

// Clamp the mode to WRITE+ before requesting update-based locks
static LockMode atLeastWrite(LockMode m) {
    return m.lessThan(LockMode.WRITE) ? LockMode.PESSIMISTIC_WRITE : m;
}
session.buildLockRequest(new LockOptions(atLeastWrite(mode))).lock(item);

Try / catch

try {
    session.buildLockRequest(new LockOptions(mode)).lock(item);
}
catch (HibernateException e) {
    if (e.getMessage().contains("not valid for locking via 'update' statement")) {
        throw new IllegalArgumentException("UpdateLockingStrategy requires LockMode.WRITE or stronger (got " + mode + ")", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A dialect that cannot 'select ... for update' maps locking to UpdateLockingStrategy, and a lock request arrives with a mode below WRITE - e.g. session.lock(entity, LockMode.PESSIMISTIC_READ) or a legacy LockMode.UPGRADE/READ - making lockMode.lessThan(LockMode.WRITE) true. Direct new UpdateLockingStrategy(persister, LockMode.PESSIMISTIC_READ) reproduces it too.

Common situations: Databases/dialects where row locks are only emulated via UPDATE; legacy code using LockMode.UPGRADE; custom dialects returning UpdateLockingStrategy for modes it cannot honor; tests constructing strategies directly.

Related errors


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