hibernate/hibernate-orm · error · ExecutionException

No JDBC mapping could be inferred for parameter - %s

Error message

No JDBC mapping could be inferred for parameter - %s

What it means

AbstractJdbcParameter.jdbcMapping() resolves the JdbcMapping for a bind: first the binding's explicit type, then the parameter's own mapping, then guessBindType() from the actual bind value. If all sources yield null - typically an untyped null bound against a parameter with no context type - it throws ExecutionException('No JDBC mapping could be inferred for parameter'). It also re-infers when the current mapping's Java type is plain Object.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/exec/internal/AbstractJdbcParameter.java:106

		final var jdbcMapping = jdbcMapping( executionContext, binding );
		bindParameterValue( jdbcMapping, statement, binding.getBindValue(), startPosition, executionContext );
	}

	private JdbcMapping jdbcMapping(ExecutionContext executionContext, JdbcParameterBinding binding) {
		JdbcMapping jdbcMapping = binding.getBindType();

		if ( jdbcMapping == null ) {
			jdbcMapping = this.jdbcMapping;
		}

		// If the parameter type is not known from the context i.e. null or Object, infer it from the bind value
		if ( jdbcMapping == null || jdbcMapping.getMappedJavaType().getJavaTypeClass() == Object.class ) {
			jdbcMapping = guessBindType( executionContext, binding.getBindValue(), jdbcMapping );
		}

		if ( jdbcMapping == null ) {
			throw new ExecutionException( "No JDBC mapping could be inferred for parameter - " + this );
		}

		return jdbcMapping;
	}

	protected void bindParameterValue(
			JdbcMapping jdbcMapping,
			PreparedStatement statement,
			Object bindValue,
			int startPosition,
			ExecutionContext executionContext)
					throws SQLException {
		//noinspection unchecked
		jdbcMapping.getJdbcValueBinder()
				.bind( statement, bindValue, startPosition, executionContext.getSession() );
	}

	private JdbcMapping guessBindType(ExecutionContext executionContext, Object bindValue, JdbcMapping jdbcMapping) {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Bind typed nulls: setParameter("p", null, StringType.INSTANCE) or setParameter("p", new TypedParameterValue<>(StandardBasicTypes.STRING, null))
  2. For native queries prefer overloads that carry types: createNativeQuery(sql, ...).setParameter(1, null, Types.VARCHAR)
  3. Register a BasicType/AttributeConverter for the value's Java type so guessBindType can resolve it
  4. Skip the parameter entirely when the value is null - build the SQL fragment conditionally

Example fix

// before
query.setParameter( "status", status ); // status is null, no type context -> throws

// after
query.setParameter( "status", new TypedParameterValue<>( StandardBasicTypes.STRING, status ) );
Defensive patterns

Strategy: validation

Validate before calling

// never bind an untyped null
if ( value == null ) {
    query.setParameter( name, new TypedParameterValue<>( StandardBasicTypes.STRING, null ) );
} else {
    query.setParameter( name, value );
}

Prevention

When it happens

Trigger: setParameter("p", null) or setParameter(1, null) on native or dynamically built queries where no type metadata exists; null binds in custom mutation executors; binding values whose class is not a registered basic type and for which guessBindType finds nothing.

Common situations: Native queries 'where col = ?' with a null argument; optional filters in dynamic-query builders bound as null; custom BasicTypes never registered; passing exotic objects (records, JSON wrappers) without a mapper.

Related errors


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