hibernate/hibernate-orm · error · UnsupportedOperationException
should only be used to bind null
Error message
should only be used to bind null
What it means
NullJdbcType is Hibernate's placeholder JdbcType for the SQL NULL type; its binder implements only doBindNull(). If it ends up as the resolved JdbcType for a parameter and a non-null value is bound to a PreparedStatement, doBind throws UnsupportedOperationException('... should only be used to bind null'). The underlying problem is that Hibernate could not determine a real JdbcType for the binding - typically an untyped query parameter.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/NullJdbcType.java:71
}
@Override
public <X> ValueBinder<X> getBinder(JavaType<X> javaType) {
return new BasicBinder<>( javaType, this ) {
@Override
protected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException {
st.setNull( index, Types.NULL );
}
@Override
protected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException {
st.setNull( name, Types.NULL );
}
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) {
throw new UnsupportedOperationException( getClass().getName() + " should only be used to bind null" );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) {
throw new UnsupportedOperationException( getClass().getName() + " should only be used to bind null" );
}
};
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Bind the parameter with an explicit type: setParameter(name, value, Integer.class) / setParameter(name, value, StringType.INSTANCE) or the typed overloads.
- For native queries prefer positional '?' placeholders combined with typed binding.
- If it happens during flush of a mapped attribute, review that attribute's @JdbcType/@Type/@JdbcTypeCode resolution so a real JdbcType is chosen.
Example fix
// before
Query q = em.createNativeQuery("select * from t where status = :p");
q.setParameter("p", "ACTIVE"); // type inference falls back to NullJdbcType
// after: bind with an explicit type
q.setParameter("p", "ACTIVE", String.class); Defensive patterns
Strategy: validation
Validate before calling
// Central typed binding helper prevents untyped parameters
static <T> void bind(jakarta.persistence.Query q, String name, T value, Class<T> type) {
if (value != null) {
q.setParameter(name, value, type); // typed overload never resolves to NullJdbcType
} else {
q.setParameter(name, null, type);
}
} Try / catch
try {
query.setParameter("p", value).getResultList();
} catch (UnsupportedOperationException e) {
if (e.getMessage() != null && e.getMessage().contains("should only be used to bind null")) {
// parameter had no resolvable JdbcType: rebind with setParameter(name, value, ExpectedType.class)
} else {
throw e;
}
} Prevention
- Always use the typed setParameter overloads for native queries
- Prefer positional '?' placeholders in native SQL
- Wrap query creation in a helper that requires an explicit parameter type
When it happens
Trigger: Binding a non-null value to a parameter whose JdbcType resolved to NullJdbcType: native queries with setParameter(name, value) and no explicit type, StoredProcedureQuery parameters registered without a concrete type, or criteria/HQL parameters whose type inference failed.
Common situations: Native queries with named parameters bound without a type hint; stored-procedure parameter registration missing the Java type; mappings where the attribute's type resolution fell back to the NULL type after refactoring.
Related errors
- 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
- Encountered unexpected content type [%s] for named native qu
- Cannot combine other returns with a collection return (" + r
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/2e67169e9a2bc99e.
Report an issue: GitHub.