hibernate/hibernate-orm · error · IllegalArgumentException

Could not resolve NativeQuery parameter type : `%s`

Error message

Could not resolve NativeQuery parameter type : `%s`

What it means

While preparing parameter bindings for a native query, JdbcParameterBindingsImpl derives each parameter's JdbcMapping from the QueryParameterBinding's bind type or the QueryParameter's Hibernate type. If that type is neither a BasicTypeReference nor a BasicValuedMapping - e.g. an entity/embedded type or an arbitrary object - it throws IllegalArgumentException('Could not resolve NativeQuery parameter type'). Native SQL parameters must map to single-column basic types.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/sql/exec/internal/JdbcParameterBindingsImpl.java:118

	}

	private JdbcMapping jdbcMapping(
			SessionFactoryImplementor factory,
			QueryParameterImplementor<?> param,
			QueryParameterBinding<?> binding) {
		final var type = determineParamType( param, binding );
		if ( type == null ) {
			return factory.getTypeConfiguration().getBasicTypeForJavaType( Object.class );
		}
		else if ( type instanceof BasicTypeReference<?> basicTypeReference ) {
			return factory.getTypeConfiguration().getBasicTypeRegistry()
					.resolve( basicTypeReference );
		}
		else if ( type instanceof BasicValuedMapping basicValuedMapping ) {
			return basicValuedMapping.getJdbcMapping();
		}
		else {
			throw new IllegalArgumentException( "Could not resolve NativeQuery parameter type : `" + param + "`");
		}
	}

	private BindableType<?> determineParamType(QueryParameterImplementor<?> param, QueryParameterBinding<?> binding) {
		final var type = binding.getBindType();
		return type == null ? param.getHibernateType() : type;
	}

	@Override
	public void addBinding(JdbcParameter parameter, JdbcParameterBinding binding) {
		if ( bindingMap == null ) {
			bindingMap = new IdentityHashMap<>();
		}
		bindingMap.put( parameter, binding );
	}

	@Override
	public Collection<JdbcParameterBinding> getBindings() {

View on GitHub (pinned to fad1729dce)

Solutions

  1. Bind a basic value instead - pass the entity's identifier: query.setParameter("p", entity.getId())
  2. Give the parameter an explicit basic type: setParameter("p", value, StandardBasicTypes.LONG)
  3. For custom types, implement BasicValuedMapping or register a BasicTypeReference for them
  4. Use the createNativeQuery overloads taking Object[]/Type[] so parameter types are supplied up front

Example fix

// before
NativeQuery<?> q = session.createNativeQuery("select * from Orders o where o.customerId = :c");
q.setParameter( "c", customer ); // entity instance -> throws

// after
q.setParameter( "c", customer.getId() );
Defensive patterns

Strategy: validation

Validate before calling

// native query parameters must be basic-typed
Object v = value instanceof EntityProxy proxy ? proxy.getIdentifier() : value;
nativeQuery.setParameter( name, v );

Type guard

boolean isNativeParameterSafe(Object value) {
    return value == null
        || value instanceof String || value instanceof Number || value instanceof Boolean
        || value instanceof java.time.temporal.Temporal || value instanceof byte[]
        || value instanceof java.util.UUID || value instanceof Enum;
}

Prevention

When it happens

Trigger: nativeQuery.setParameter(p, entityInstance) or binding an embedded/array value; setParameter with a custom Type that is not basic-valued; using a QueryParameter whose Hibernate type is an EntityType (association passed as a native query parameter).

Common situations: Mixing HQL-style entity parameters into native SQL; migrating an HQL query to native SQL while keeping entity-typed parameters; custom UserType implementations that do not implement BasicValuedMapping.

Related errors


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