hibernate/hibernate-orm · error · UnsupportedMappingException

MappedSuperclassType cannot be used to create an SqmPath - t

Error message

MappedSuperclassType cannot be used to create an SqmPath - that would be an SqmFrom which are created directly

What it means

MappedSuperclassTypeImpl.createSqmPath unconditionally throws UnsupportedMappingException: a @MappedSuperclass domain type can never be the source of an SqmPath, because SQM paths must grow from an SqmFrom (an entity root or join). It is a hard API contract, not a runtime state check.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/metamodel/model/domain/internal/MappedSuperclassTypeImpl.java:147

	@Nonnull
	public BindableType getBindableType() {
		return ENTITY_TYPE;
	}

	@Override
	@Nonnull
	public PersistenceType getPersistenceType() {
		return MAPPED_SUPERCLASS;
	}

	@Override
	protected boolean isIdMappingRequired() {
		return false;
	}

	@Override
	public SqmPath<J> createSqmPath(SqmPath<?> lhs, @Nullable SqmPathSource<?> intermediatePathSource) {
		throw new UnsupportedMappingException(
				"MappedSuperclassType cannot be used to create an SqmPath - that would be an SqmFrom which are created directly"
		);
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Make the shared base class an @Entity with an @Inheritance strategy instead of @MappedSuperclass when it must be a query root
  2. Query a concrete @Entity subclass (or any subclass — Hibernate folds in siblings via polymorphism) instead of the mapped superclass
  3. In generic repository code, constrain/receive the entity class rather than the mapped-superclass class

Example fix

// before
@MappedSuperclass
public abstract class BaseEntity { @Id Long id; }
// query against the superclass
em.createQuery("select b from BaseEntity b", BaseEntity.class); // path/root resolution fails

// after
@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BaseEntity { @Id Long id; }
// now a valid polymorphic root
Defensive patterns

Strategy: type-guard

Validate before calling

// Reject mapped-superclass query domains before touching SQM
if (domainClass.isAnnotationPresent(jakarta.persistence.MappedSuperclass.class)) {
  throw new IllegalArgumentException(
      domainClass.getName() + " is a @MappedSuperclass and cannot be a query root; query a concrete @Entity subclass");
}

Type guard

static boolean isQueryableType(Metamodel metamodel, Class<?> cls) {
  if (!cls.isAnnotationPresent(jakarta.persistence.Entity.class)
      && !cls.isAnnotationPresent(jakarta.persistence.MappedSuperclass.class)) {
    return false;
  }
  try {
    metamodel.managedType(cls);
    return !cls.isAnnotationPresent(jakarta.persistence.MappedSuperclass.class)
        || metamodel.getEntities().stream().anyMatch(e -> cls.isAssignableFrom(e.getJavaType()));
  } catch (IllegalArgumentException e) {
    return false;
  }
}

Prevention

When it happens

Trigger: Attempting to build an SQM path whose path source is a mapped superclass type — e.g. via JpaMetamodel.managedType(...) then createSqmPath, treat()/as() targeting a @MappedSuperclass-typed expression, or a custom criteria/QueryEngine extension walking attributes whose declaring type is a mapped superclass without an entity lhs.

Common situations: Porting code where the base class used to be an @Entity; trying to write polymorphic queries against a shared @MappedSuperclass (e.g. a common 'BaseEntity' with id/version); generic repositories that accept the mapped-superclass class literal as the domain type.

Related errors


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