hibernate/hibernate-orm · error · SemanticException

Composite query parameter cannot be used in select

Error message

Composite query parameter cannot be used in select

What it means

When a query parameter's resolved SQL expression is an SqlTuple (multiple columns - an embeddable, composite user type, or composite/embeddedId key), it cannot be projected as a single select item: JDBC has no single binding for a tuple in the select list. SqmParameterInterpretation.createDomainResult therefore throws SemanticException('Composite query parameter cannot be used in select') at SQL-AST creation time. The query fails at creation, never at execution.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/SqmParameterInterpretation.java:87

	}

	@Override
	public void accept(SqlAstWalker sqlTreeWalker) {
		getResolvedExpression().accept( sqlTreeWalker );
	}

	@Override
	public MappingModelExpressible<?> getExpressionType() {
		return valueMapping;
	}

	@Override
	public DomainResult<?> createDomainResult(
			String resultVariable,
			DomainResultCreationState creationState) {
		final var resolvedExpression = getResolvedExpression();
		if ( resolvedExpression instanceof SqlTuple ) {
			throw new SemanticException( "Composite query parameter cannot be used in select" );
		}

		final var jdbcMapping = resolvedExpression.getExpressionType().getSingleJdbcMapping();
		final var sqlAstCreationState = creationState.getSqlAstCreationState();
		final var sqlSelection =
				sqlAstCreationState.getSqlExpressionResolver()
						.resolveSqlSelection(
								resolvedExpression,
								jdbcMapping.getJdbcJavaType(),
								null,
								sqlAstCreationState.getCreationContext().getTypeConfiguration()
						);
		return new BasicResult(
				sqlSelection.getValuesArrayPosition(),
				resultVariable,
				jdbcMapping.getMappedJavaType(),
				jdbcMapping.getValueConverter(),
				null,

View on GitHub (pinned to fad1729dce)

Solutions

  1. Select the component attributes explicitly: 'select :empId.part1, :empId.part2 ...' is not supported either - instead select the entity's own components 'select e.id.a, e.id.b' and bind the parameter only in WHERE
  2. Bind the composite parameter only in comparison predicates (where e.id = :empId), never in SELECT or ORDER BY
  3. If you need the value back, return it from Java: query the where clause with the parameter and prepend the bound value client-side
  4. Avoid parameters as select items entirely - use literals or entity attributes in the select list

Example fix

-- before
select :deptPk from Department d where d.pk = :deptPk -- deptPk is @EmbeddedId
-- after
select d.pk.code, d.pk.region from Department d where d.pk = :deptPk
Defensive patterns

Strategy: validation

Validate before calling

// Reject composite parameters before query creation if they appear as select items
if (paramValue != null && em.getMetamodel() instanceof MetamodelImpl) {
    Class<?> pc = paramValue.getClass();
    boolean embeddable = pc.isAnnotationPresent(jakarta.persistence.Embeddable.class);
    if (embeddable && hqlSelectItems.contains(":" + paramName)) throw new IllegalArgumentException("composite param in select");
}

Type guard

static boolean isComposite(EntityManager em, Object v) {
    return v != null && em.getMetamodel().getEmbeddables().stream()
        .anyMatch(et -> et.getJavaType() == v.getClass());
}

Try / catch

catch (SemanticException e) { if (e.getMessage().contains("Composite query parameter")) { /* move param to WHERE, select entity components instead */ } else throw e; }

Prevention

When it happens

Trigger: HQL 'select :empId from Employee e' where :empId is bound to an EmbeddedId/composite value; criteria multiselect(cb.parameter(EmbeddedId.class)) or selecting a parameter whose type resolves to an embeddable; 'select e.id from ...' variants where e.id is an embedded id get inlined fine, but explicitly binding a composite parameter into the select list triggers it

Common situations: Reports trying to echo a composite filter value back as a result column; mapping a primary key as @EmbeddedId (composite key) and writing generic queries that project bound parameters; migrating from Hibernate 5 where some tuple-in-select cases were tolerated or rendered differently.

Related errors


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