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
- Use one style consistently: convert the bare '?' into a named parameter (':y') or convert everything to JPA ordinals (?1, ?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.
- 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
- Pick one parameter style per codebase module and enforce it in review/lint.
- For PostgreSQL JSONB '?'-operators in native SQL, set hibernate.query.native.ignore_jdbc_parameters=true or use jsonb_exists/jsonb_exists_any functions.
- Run validateSingleParameterStyle in tests over native SQL constants.
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
- Could not resolve NativeQuery parameter type : `%s`
- Unable to locate JdbcValueDescriptor for column `%s`
- Named native query definition object is null
- Named native query definition name is null: {}
- Named native query [%s] specified both a resultset-ref and a
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/f14836060e08ffd4.
Report an issue: GitHub.