hibernate/hibernate-orm · error · IllegalArgumentException

No assignments specified as part of UPDATE criteria

Error message

No assignments specified as part of UPDATE criteria

What it means

Before an UPDATE statement is executed, SqmUpdateStatement.validate() checks the SET clause contains at least one assignment. A criteria update built with cb.createCriteriaUpdate(...) but without any set(...) call has nothing to update, and Hibernate throws IllegalArgumentException. HQL updates always carry assignments syntactically, so this error is essentially criteria-only.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/update/SqmUpdateStatement.java:156

				new SqmUpdateStatement<>(
						nodeBuilder(),
						newQuerySource == null ? getQuerySource() : newQuerySource,
						copyParameters( context ),
						copyCteStatements( context ),
						getTarget().copy( context ),
						versioned
				)
		);
		statement.setWhereClause( copyWhereClause( context ) );
		statement.setClause = setClause.copy( context );
		return statement;
	}

	@Override
	public void validate(@Nullable String hql) {
		verifyImmutableEntityUpdate( hql );
		if ( getSetClause().getAssignments().isEmpty() ) {
			throw new IllegalArgumentException( "No assignments specified as part of UPDATE criteria" );
		}
		if ( getQuerySource() == SqmQuerySource.CRITERIA ) {
			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 );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Add at least one set(...) before creating/executing the query — verify update.getSetClause()/assignments are non-empty if you keep a reference to the Hibernate API
  2. In dynamic builders, skip execution entirely when no assignments were produced (an empty update is usually a no-op anyway)
  3. Fail fast with your own validation right after building, so the message points at your code rather than Hibernate internals

Example fix

// before
CriteriaUpdate<User> u = cb.createCriteriaUpdate(User.class);
Root<User> root = u.from(User.class);
u.where(cb.equal(root.get("id"), userId));
// no u.set(...) — nothing to update
em.createQuery(u).executeUpdate(); // IllegalArgumentException

// after
if (changes.isEmpty()) { return; } // nothing changed, skip
changes.forEach((attr, val) -> u.set(root.get(attr), val));
em.createQuery(u).executeUpdate();
Defensive patterns

Strategy: validation

Validate before calling

if (changes.isEmpty()) { return 0; } // nothing to update — skip before building
CriteriaUpdate<T> u = cb.createCriteriaUpdate(entity);
changes.forEach((attr, val) -> u.set(root.get(attr), val));

Try / catch

try { return em.createQuery(update).executeUpdate(); } catch (IllegalArgumentException e) { if (e.getMessage().contains("No assignments")) { return 0; } else throw e; }

Prevention

When it happens

Trigger: CriteriaUpdate<T> update = cb.createCriteriaUpdate(T.class); update.where(...); em.createQuery(update).executeUpdate() — with no update.set(attribute, value) call, typically because a dynamic builder's set-list came out empty.

Common situations: Dynamically composed updates whose assignments are driven by a diff/patch map that is empty (nothing changed); refactors that move set() calls behind a condition; copy-pasted update templates missing the set line.

Related errors


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