hibernate/hibernate-orm · error · ParameterRecognitionException

Cannot mix parameter styles between JDBC-style, ordinal and

Error message

Cannot mix parameter styles between JDBC-style, ordinal and named in the same query

What it means

ParameterRecognizerImpl enforces one parameter style per query: a bare JDBC '?' sets ParameterStyle.JDBC. When a bare '?' is recognized after a named (':name') or JPA-ordinal ('?n') parameter was already seen, parameterStyle is NAMED and this ParameterRecognitionException is thrown. Mixing styles would make bind positions ambiguous, so Hibernate rejects it up front.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/query/sql/internal/ParameterRecognizerImpl.java:100

	public ArrayList<ParameterOccurrence> getParameterList() {
		return parameterList;
	}

	public String getAdjustedSqlString() {
		return sqlStringBuffer.toString();
	}

	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Recognition code

	@Override
	public void ordinalParameter(int sourcePosition) {
		if ( parameterStyle == null ) {
			parameterStyle = ParameterStyle.JDBC;
		}
		else if ( parameterStyle != ParameterStyle.JDBC ) {
			throw new ParameterRecognitionException( "Cannot mix parameter styles between JDBC-style, ordinal and named in the same query" );
		}

		int implicitPosition = ordinalParameterImplicitPosition++;

		QueryParameterImplementor<?> parameter = null;

		if ( positionalQueryParameters == null ) {
			positionalQueryParameters = new HashMap<>();
		}
		else {
			parameter = positionalQueryParameters.get( implicitPosition );
		}

		if ( parameter == null ) {
			parameter = QueryParameterPositionalImpl.fromNativeQuery( implicitPosition );
			positionalQueryParameters.put( implicitPosition, parameter );
		}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use one style consistently: convert the bare '?' into a named parameter (':y') or convert everything to JPA ordinals (?1, ?2).
  2. For literal '?' operators in PostgreSQL JSONB SQL, replace them with the equivalent functions (jsonb_exists, jsonb_exists_any, jsonb_exists_all) or set hibernate.query.native.ignore_jdbc_parameters=true so bare '?' is not treated as a parameter.
  3. Escape/inline literal question marks through dialect-safe function calls instead of raw operators.

Example fix

-- before
select * from person where x = :val and y = ?

-- after
select * from person where x = :val and y = :y
Defensive patterns

Strategy: validation

Validate before calling

static void validateSingleParameterStyle(String sql) {
    String scrubbed = sql.replaceAll("'([^']*)'", "?").replaceAll("\"([^\"]*)\"", "?"); // ignore literals
    var m = java.util.regex.Pattern.compile("\\?(\\d+)\\b|:(\\w+)|\\?").matcher(scrubbed);
    boolean jdbc = false, namedOrOrdinal = false;
    while (m.find()) {
        if (m.group(1) != null || m.group(2) != null) namedOrOrdinal = true;
        else jdbc = true;
    }
    if (jdbc && namedOrOrdinal) throw new IllegalArgumentException("Query mixes bare '?' with ':name'/'?n' parameters");
}

Try / catch

try { session.createNativeQuery(sql); } catch (org.hibernate.query.ParameterRecognitionException e) { /* normalize all parameters to one style and rebuild the query */ throw e; }

Prevention

When it happens

Trigger: A query string combining ':name' or '?1' with a bare '?', e.g. "... where x = :val and y = ?". The bare '?' can also come from literal SQL such as PostgreSQL JSONB operators (? ?| ?&) which the parser cannot distinguish from placeholders. Thrown at query creation during ParameterRecognizer callbacks.

Common situations: PostgreSQL JSONB queries using the ? / ?| / ?& operators alongside real named parameters; copy-pasted SQL fragments in different styles; partial migration of a query from '?' to ':name'.

Related errors


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