hibernate/hibernate-orm · error · UnsupportedOperationException

Sets don't support updating by element

Error message

Sets don't support updating by element

What it means

PersistentCollection.getSnapshotElement(entry, i) supplies the element's snapshot state used to decide whether an existing row needs an UPDATE. PersistentSet explicitly reports isRowUpdatePossible() == false — set rows are deleted and re-inserted, never updated — so it cannot provide snapshot elements and throws when asked. Getting here means dirty-check/flush logic (or custom code) expects row updates on a set, the same mapping-mismatch family as getIndex.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/collection/spi/PersistentSet.java:421

	@Override
	public boolean isRowUpdatePossible() {
		return false;
	}

	@Override
	public Object getIndex(Object entry, int i, CollectionPersister persister) {
		throw new UnsupportedOperationException("Sets don't have indexes");
	}

	@Override
	public Object getElement(Object entry) {
		return entry;
	}

	@Override
	public Object getSnapshotElement(Object entry, int i) {
		throw new UnsupportedOperationException("Sets don't support updating by element");
	}

	@Override
	@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
	public boolean equals(Object other) {
		read();
		return set.equals( other );
	}

	@Override
	public int hashCode() {
		read();
		return set.hashCode();
	}

	@Override
	public boolean entryExists(Object key, int i) {
		return key != null;

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make the mapping match set semantics: plain @OneToMany Set / <set>, no index or update-oriented metadata
  2. If elements really are updated in place, map the association as a List/Map or a component collection that supports row updates
  3. Search for custom code calling getSnapshotElement/isRowUpdatePossible on PersistentSet and branch on collection kind
  4. Re-run schema/mapping validation (SessionFactory boot) after every collection type change

Example fix

// before: Set treated as updatable/indexed collection
@OneToMany
@OrderColumn(name = "pos")
private Set<Item> items = new HashSet<>();

// after: unordered set, delete-and-reinsert semantics
@OneToMany
private Set<Item> items = new HashSet<>();
Defensive patterns

Strategy: type-guard

Validate before calling

if (persistentCollection instanceof org.hibernate.collection.spi.PersistentSet && codePathExpectsRowUpdates()) {
    throw new IllegalStateException("Sets use delete+insert semantics; row updates are not possible");
}

Type guard

boolean supportsRowUpdates(org.hibernate.collection.spi.PersistentCollection<?> collection) {
    return !(collection instanceof org.hibernate.collection.spi.PersistentSet); // isRowUpdatePossible() == false
}

Try / catch

try {
    Object snap = collection.getSnapshotElement(entry, i);
} catch (UnsupportedOperationException e) {
    // set semantics: compare whole collection, not per-row updates
    rebuildFromScratch(collection);
}

Prevention

When it happens

Trigger: A persister or custom code path performing per-element snapshot comparison against a PersistentSet: typically a mapping that implies updatable/indexed collection semantics applied to a Set attribute, or direct internal API calls on the PersistentSet instance.

Common situations: Same drift as 'Sets don't have indexes': index or update-oriented metadata left on a field that became a Set; custom collection persisters assuming row updates; copying collections between persistent contexts with mismatched semantics.

Related errors


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