hibernate/hibernate-orm · error · QueryException

Can't emulate json_objectagg 'with unique keys' clause.

Error message

Can't emulate json_objectagg 'with unique keys' clause.

What it means

SAP HANA lacks native json_objectagg, so Hibernate emulates it with string_agg. The emulation cannot enforce key uniqueness, so a WITH UNIQUE KEYS request is rejected with this QueryException before SQL is generated.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/dialect/function/json/HANAJsonObjectAggFunction.java:37

/**
 * SAP HANA json_objectagg function.
 */
public class HANAJsonObjectAggFunction extends JsonObjectAggFunction {

	public HANAJsonObjectAggFunction(TypeConfiguration typeConfiguration) {
		super( ",", false, typeConfiguration );
	}

	@Override
	protected void render(
			SqlAppender sqlAppender,
			JsonObjectAggArguments arguments,
			Predicate filter,
			ReturnableType<?> returnType,
			SqlAstTranslator<?> translator) {
		final boolean caseWrapper = filter != null;
		if ( arguments.uniqueKeysBehavior() == JsonObjectAggUniqueKeysBehavior.WITH ) {
			throw new QueryException( "Can't emulate json_objectagg 'with unique keys' clause." );
		}
		sqlAppender.appendSql( "'{'||string_agg(" );
		renderArgument( sqlAppender, arguments.key(), JsonNullBehavior.NULL, translator );
		sqlAppender.appendSql( "||':'||" );
		if ( caseWrapper ) {
			if ( arguments.nullBehavior() != JsonNullBehavior.ABSENT ) {
				throw new QueryException( "Can't emulate json_objectagg filter clause when using 'null on null' clause." );
			}
			translator.getCurrentClauseStack().push( Clause.WHERE );
			sqlAppender.appendSql( "case when " );
			filter.accept( translator );
			translator.getCurrentClauseStack().pop();
			sqlAppender.appendSql( " then " );
			renderArgument( sqlAppender, arguments.value(), arguments.nullBehavior(), translator );
			sqlAppender.appendSql( " else null end)" );
		}
		else {
			renderArgument( sqlAppender, arguments.value(), arguments.nullBehavior(), translator );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Remove WITH UNIQUE KEYS from the json_objectagg call on HANA.
  2. Deduplicate key/value pairs in a subquery or in Java before the aggregate.
  3. Use a native HANA query when unique-key enforcement must stay in the database.
  4. Validate keys for uniqueness in application code after the aggregate returns.

Example fix

// before
select json_objectagg(k value v with unique keys) from Entity e

// after
select json_objectagg(k value v) from Entity e
Defensive patterns

Strategy: try-catch

Validate before calling

boolean hana = session.getJdbcServices().getDialect() instanceof org.hibernate.dialect.HANADialect;
if (hana && withUniqueKeys) {
    throw new UnsupportedOperationException("HANA json_objectagg cannot enforce WITH UNIQUE KEYS; deduplicate first");
}

Try / catch

try {
    return session.createQuery(hql).getSingleResult();
} catch (org.hibernate.QueryException e) {
    if (e.getMessage() != null && e.getMessage().contains("with unique keys")) {
        // Retry without WITH UNIQUE KEYS after deduplicating in a subquery.
        return session.createQuery(fallbackHql).getSingleResult();
    }
    throw e;
}

Prevention

When it happens

Trigger: An HQL query on HANA calls json_objectagg(key VALUE value WITH UNIQUE KEYS). The check arguments.uniqueKeysBehavior() == JsonObjectAggUniqueKeysBehavior.WITH fires and rendering stops.

Common situations: Queries ported from Oracle or MySQL 8, where WITH UNIQUE KEYS is supported. Mappings that produce duplicate keys per group and rely on the database to drop duplicates.

Related errors


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