hibernate/hibernate-orm · error · UnsupportedOperationException
dynamic instantiation in a sub-query is unsupported
Error message
dynamic instantiation in a sub-query is unsupported
What it means
DynamicInstantiation models 'select new X(...) ...' (constructor or list/map injection) in the SELECT clause. It supports building a DomainResult for the top-level query, but when the dynamic instantiation ends up inside a sub-query, applySqlSelections() is called on it and it throws UnsupportedOperationException('dynamic instantiation in a sub-query is unsupported') - Hibernate cannot propagate instantiation targets through the subquery boundary into SQL select items.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiation.java:111
}
@Override
public DomainResult<T> createDomainResult(
String resultVariable,
DomainResultCreationState creationState) {
return new DynamicInstantiationResultImpl<>(
resultVariable,
getNature(),
getTargetJavaType(),
getArguments().stream()
.map( argument -> argument.buildArgumentDomainResult( creationState ) )
.collect( toList() )
);
}
@Override
public void applySqlSelections(DomainResultCreationState creationState) {
throw new UnsupportedOperationException( "dynamic instantiation in a sub-query is unsupported" );
}
//
// @SuppressWarnings("unchecked")
// private static DomainResultAssembler resolveAssembler(
// DynamicInstantiation dynamicInstantiation,
// boolean areAllArgumentsAliased,
// boolean areAnyArgumentsAliased,
// List<String> duplicatedAliases,
// List<ArgumentReader<?>> argumentReaders,
// AssemblerCreationState creationState) {
//
// if ( dynamicInstantiation.getNature() == DynamicInstantiationNature.LIST ) {
// if ( LOG.isDebugEnabled() && areAnyArgumentsAliased ) {
// LOG.debug( "One or more arguments for List dynamic instantiation (`new list(...)`) specified an alias; ignoring" );
// }
// return new DynamicInstantiationListAssemblerImpl(
// (JavaType<List>) dynamicInstantiation.getTargetJavaType(),View on GitHub (pinned to fad1729dce)
Solutions
- Move the instantiation to the outer query: the subquery selects plain values (ids, scalars) and the outer select wraps them.
- Replace the subquery with a join so no instantiation is needed inside it.
- Fetch the raw subquery results first, then build the objects in Java (stream + map to DTO).
- Check the Hibernate JIRA and latest 6.x patch - restrictions around instantiation positions have shifted across releases.
Example fix
// before
em.createQuery("select o from Order o where o.id in " +
"(select new com.acme.OrderRef(o2.id, o2.code) from Order o2 where o2.active = true)");
// after
em.createQuery("select new com.acme.OrderRef(o.id, o.code) from Order o " +
"where o.id in (select o2.id from Order o2 where o2.active = true)"); Defensive patterns
Strategy: validation
Validate before calling
// Fail fast at startup: parsing the query builds the plan and throws immediately
try (EntityManager em = emf.createEntityManager()) {
em.createQuery("select new com.acme.OrderRef(o.id, o.code) from Order o", OrderRef.class);
}
// And guard the JPQL string: no 'select new' inside a parenthesized subquery
String flat = jpql.toLowerCase().replaceAll("\\s+", " ");
if (flat.matches("(?s).*\\(\\s*select\\s+new\\b.*")) {
throw new IllegalArgumentException("dynamic instantiation inside a sub-query is unsupported");
} Try / catch
try {
results = em.createQuery(jpql, Pair.class).getResultList();
} catch (UnsupportedOperationException e) {
if ("dynamic instantiation in a sub-query is unsupported".equals(e.getMessage())) {
// rewrite: instantiate in the outer query, select plain values in the subquery
} else { throw e; }
} Prevention
- Keep constructor expressions in the outermost SELECT only; subqueries select ids/scalars.
- Declare projections as @NamedQuery so the plan is validated at bootstrap, not first use.
- Add a query review rule: 'new ...' may not appear inside parentheses of a subquery.
When it happens
Trigger: Using a constructor expression / dynamic instantiation inside a subquery, e.g. `where o.id in (select new com.acme.Pair(o2.id, o2.code) from Order o2)` or criteria subquery selections; dynamic instantiation nested in a query used as a derived table or in processing paths that require SQL selections from the subquery.
Common situations: Copy-pasting a working top-level projection into an exists/in subquery; criteria queries reusing a selection inside SubQuery expression lists; upgrading queries that worked in older 5.x builds where the restriction was less strict.
Related errors
- Domain result for non-scalar subquery shouldn't be created
- Injection of parent instance into embeddable result is not p
- Error performing the dynamic instantiation
- Error instantiating class '{}'
- Cannot set field '{}' to instantiate '{}'
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/fada92507bd48435.
Report an issue: GitHub.