hibernate/hibernate-orm · error · SemanticException
Target type '%s' is not an entity
Error message
Target type '%s' is not an entity
What it means
When you set the target of a criteria UPDATE, SqmUpdateStatement.setTarget rejects roots whose model is an SqmPolymorphicRootDescriptor — Hibernate's synthetic type that stands for 'several entities at once' (e.g., a MappedSuperclass/abstract hierarchy root or an explicit polymorphic reference). There is no single entity to update in that case, so a SemanticException 'Target type ... is not an entity' is thrown.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/tree/spi/update/SqmUpdateStatement.java:272
return versioned;
}
@Override
public SqmUpdateStatement<T> versioned() {
this.versioned = true;
return this;
}
@Override
public SqmUpdateStatement<T> versioned(boolean versioned) {
this.versioned = versioned;
return this;
}
@Override
public void setTarget(@Nonnull JpaRoot<T> root) {
if ( root.getModel() instanceof SqmPolymorphicRootDescriptor<?> ) {
throw new SemanticException(
String.format(
"Target type '%s' is not an entity",
root.getModel().getHibernateEntityName()
)
);
}
super.setTarget( root );
}
@Nonnull
@Override
public SqmUpdateStatement<T> where(@Nonnull Expression<Boolean> restriction) {
setWhere( restriction );
return this;
}
@Nonnull
@OverrideView on GitHub (pinned to fad1729dce)
Solutions
- Target a concrete @Entity subtype in createCriteriaUpdate(...) and in the root you pass to setTarget(...)
- If all subtypes need updating, iterate the concrete subtypes (from metamodel.getEntities() or your known list) and execute one update per entity
- Reconsider the design: polymorphic bulk updates across unioned entity tables are not expressible as a single SQL statement anyway
Example fix
// before
@MappedSuperclass abstract class BaseEvent { ... }
CriteriaUpdate<BaseEvent> u = cb.createCriteriaUpdate(BaseEvent.class); // polymorphic root
u.setTarget(u.from(BaseEvent.class)); // SemanticException: Target type is not an entity
// after — one update per concrete entity
for (Class<?> concrete : List.of(LoginEvent.class, PurchaseEvent.class)) {
@SuppressWarnings("unchecked")
CriteriaUpdate<BaseEvent> u = (CriteriaUpdate<BaseEvent>) cb.createCriteriaUpdate(concrete);
Root<BaseEvent> r = (Root<BaseEvent>) u.from(concrete);
u.set(r.get("archived"), true);
em.createQuery(u).executeUpdate();
} Defensive patterns
Strategy: validation
Validate before calling
if (AbstractSuperclass.class.isAssignableFrom(targetType) && !targetType.isAnnotationPresent(jakarta.persistence.Entity.class)) {
throw new IllegalArgumentException("Update target must be a concrete @Entity, got " + targetType);
} Type guard
static boolean isConcreteEntity(Class<?> c) { return c.isAnnotationPresent(jakarta.persistence.Entity.class); } Try / catch
try { update.setTarget(root); } catch (SemanticException e) { if (e.getMessage().contains("not an entity")) { /* rebuild update against a concrete subtype */ } else throw e; } Prevention
- Type generic update services by concrete entity classes, constrain generics with @Entity-typed parameters
- Validate the target is annotated @Entity before building a CriteriaUpdate
- For hierarchies, keep an explicit list of concrete subtypes and loop over it for bulk updates
When it happens
Trigger: cb.createCriteriaUpdate(AbstractSuperclass.class) where AbstractSuperclass is a @MappedSuperclass (or polymorphic-typed root), then setTarget(root) — or building the update directly from a root of a non-entity abstract type.
Common situations: Inheritance hierarchies where services are typed against the abstract base; generic update helpers parameterized on a base class; code migrated from HQL updates on superclasses, which have their own restrictions.
Related errors
- Cannot interpret discriminator value ({discriminatorRole}) :
- Not a treatable type: ${treatJavaType.getName()}
- Cannot call getParent() on update/delete criteria
- No assignments specified as part of UPDATE criteria
- Expected object of type `%s`, but found `%s`; discriminator
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/4f5b26fadc19a828.
Report an issue: GitHub.