hibernate/hibernate-orm · error · UnsupportedOperationException

Recognizing native query as a function call is no longer sup

Error message

Recognizing native query as a function call is no longer supported

What it means

Before parsing, ParameterParser.checkIsNotAFunctionCall rejects the legacy JDBC function-call escape form: a query wrapped in '{...}' whose prefix (ignoring whitespace and case) matches '?=call'. Hibernate 6 no longer recognizes native queries written as '{? = call myFunc(...)}' as stored-function calls and throws UnsupportedOperationException instead of silently misinterpreting it.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sql/internal/ParameterParser.java:241

		final String fixture = "?=call";
		int fixturePosition = 0;
		boolean matches = true;
		final int max = checkString.length();
		for ( int i = 0; i < max; i++ ) {
			final char c = Character.toLowerCase( checkString.charAt( i ) );
			if ( Character.isWhitespace( c ) ) {
				continue;
			}
			if ( c == fixture.charAt( fixturePosition ) ) {
				fixturePosition++;
				continue;
			}
			matches = false;
			break;
		}

		if ( matches ) {
			throw new UnsupportedOperationException(
					"Recognizing native query as a function call is no longer supported" );

		}
	}

}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Rewrite the call as a scalar native query: select myFunc(?) and read the single result (optionally with an explicit result type).
  2. For stored procedures with OUT parameters, use session.createStoredProcedureCall(...) or em.createStoredProcedureQuery(...) which handle parameter registration properly.
  3. If the wrapped text is not meant as a function call, remove the enclosing braces so the pattern no longer matches '?=call'.

Example fix

// before
List<?> r = session.createNativeQuery("{? = call calculate_total(:id)}").getResultList(); // UnsupportedOperationException

// after
BigDecimal total = session.createNativeQuery("select calculate_total(:id)", BigDecimal.class)
        .setParameter("id", id)
        .getSingleResult();
Defensive patterns

Strategy: validation

Validate before calling

static void assertNotLegacyFunctionCall(String sql) {
    if (sql.trim().matches("(?i)\\{\\s*\\?\\s*=\\s*call.*}")) throw new UnsupportedOperationException("Rewrite {? = call f(?)} as select f(?) or use createStoredProcedureCall");
}

Try / catch

try { session.createNativeQuery(sql); } catch (UnsupportedOperationException e) { if (e.getMessage().contains("function call")) { /* rewrite to select f(...) or StoredProcedureCall */ } else throw e; }

Prevention

When it happens

Trigger: Creating any native query whose trimmed text starts with '{', ends with '}', and whose leading part before 'call' matches '?=' — e.g. session.createNativeQuery("{? = call calculate_total(:id)}"). The check runs first in ParameterParser.parse, so it fails immediately at query creation.

Common situations: Applications migrated from Hibernate 5 or plain JDBC where '{? = call ...}' was the standard way to call stored functions and read the return value; stored-function code copied from old EJB/Hibernate tutorials.

Related errors


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