hibernate/hibernate-orm · error · IllegalQueryOperationException
Locking with set operators is not supported
Error message
Locking with set operators is not supported
What it means
Oracle cannot apply FOR UPDATE to a SELECT participating in a set operation (union/intersect/minus; see the Oracle docs link in the source). OracleLegacySqlAstTranslator.determineLockingStrategy() normally degrades to follow-on locking (rows locked by a follow-up query); when follow-on locking is disallowed (FollowOn.DISALLOW, e.g. hibernate.query.followOnLocking=false) it throws IllegalQueryOperationException instead as soon as the query group contains set operators.
Source
Thrown at hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacySqlAstTranslator.java:158
}
super.visitSqlSelection( sqlSelection );
}
@Override
protected LockStrategy determineLockingStrategy(
QuerySpec querySpec,
Locking.FollowOn followOnStrategy) {
if ( followOnStrategy == Locking.FollowOn.FORCE ) {
return LockStrategy.FOLLOW_ON;
}
LockStrategy strategy = super.determineLockingStrategy( querySpec, followOnStrategy );
// Oracle also doesn't support locks with set operators
// See https://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_10002.htm#i2066346
if ( strategy != LockStrategy.FOLLOW_ON && isPartOfQueryGroup() ) {
if ( followOnStrategy == Locking.FollowOn.DISALLOW ) {
throw new IllegalQueryOperationException( "Locking with set operators is not supported" );
}
else if ( followOnStrategy != Locking.FollowOn.IGNORE ) {
strategy = LockStrategy.NONE;
}
else {
strategy = LockStrategy.FOLLOW_ON;
}
}
if ( strategy != LockStrategy.FOLLOW_ON && hasSetOperations( querySpec ) ) {
if ( followOnStrategy == Locking.FollowOn.DISALLOW ) {
throw new IllegalQueryOperationException( "Locking with set operators is not supported" );
}
else if ( followOnStrategy != Locking.FollowOn.IGNORE ) {
strategy = LockStrategy.NONE;
}
else {
strategy = LockStrategy.FOLLOW_ON;View on GitHub (pinned to fad1729dce)
Solutions
- Re-enable follow-on locking (remove the hibernate.query.followOnLocking=false setting) so Hibernate applies the lock in a follow-up select
- Restructure the query to remove set operators around the locked query spec (compose results in the application)
- Run the union query unlocked and lock rows separately with a native 'select ... for update' on the key set
Example fix
// before: follow-on locking disallowed + union
List<Order> l = session.createQuery( unionHql, Order.class )
.setLockMode( "o", LockMode.PESSIMISTIC_WRITE )
.list(); // -> IllegalQueryOperationException
// after: allow follow-on locking (drop hibernate.query.followOnLocking=false)
List<Order> l = session.createQuery( unionHql, Order.class )
.setLockMode( "o", LockMode.PESSIMISTIC_WRITE ) // follow-up select applies the lock
.list(); Defensive patterns
Strategy: try-catch
Validate before calling
boolean hasSetOps(String hql) {
return hql != null && hql.toLowerCase( Locale.ROOT ).matches( "(?s).*\\b(union|intersect|except)\\b.*" );
}
if ( hasSetOps( hql ) && lockMode.greaterThan( LockMode.OPTIMISTIC ) ) {
// run unlocked or allow follow-on locking instead of failing translation
} Try / catch
try {
return query.list();
}
catch ( IllegalQueryOperationException e ) {
if ( e.getMessage() != null && e.getMessage().contains( "set operators" ) ) {
query.setLockOptions( LockOptions.NONE ); // re-run unlocked, lock separately by ids
return query.list();
}
throw e;
} Prevention
- Do not disable follow-on locking globally on Oracle if any query uses set operators
- Lock a simple id query and hydrate from it instead of locking a union
- Add integration tests with production-shaped HQL plus pessimistic locks
When it happens
Trigger: HQL/Criteria using union/intersect/except combined with a pessimistic lock (setLockMode(PESSIMISTIC_WRITE) or LockOptions) while follow-on locking is disabled, on OracleLegacyDialect.
Common situations: Follow-on locking switched off globally for performance; a pessimistic lock added to an existing union-based search or report query; pagination plus locking on merged result sets.
Related errors
- Locking with set operators is not supported
- {unit} is not a legal field
- unrecognized field: {unit}
- Locking with OFFSET/FETCH is not supported
- Locking with set operators is not supported!
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/e9ef413c2e1f949c.
Report an issue: GitHub.