{"record":{"id":"2e67169e9a2bc99e","repo":"hibernate/hibernate-orm","slug":"should-only-be-used-to-bind-null","errorCode":null,"errorMessage":" should only be used to bind null","messagePattern":" should only be used to bind null","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/NullJdbcType.java","lineNumber":71,"sourceCode":"\t}\n\n\t@Override\n\tpublic <X> ValueBinder<X> getBinder(JavaType<X> javaType) {\n\t\treturn new BasicBinder<>( javaType, this ) {\n\n\t\t\t@Override\n\t\t\tprotected void doBindNull(PreparedStatement st, int index, WrapperOptions options) throws SQLException {\n\t\t\t\tst.setNull( index, Types.NULL );\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tprotected void doBindNull(CallableStatement st, String name, WrapperOptions options) throws SQLException {\n\t\t\t\tst.setNull( name, Types.NULL );\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tprotected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) {\n\t\t\t\tthrow new UnsupportedOperationException( getClass().getName() + \" should only be used to bind null\" );\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tprotected void doBind(CallableStatement st, X value, String name, WrapperOptions options) {\n\t\t\t\tthrow new UnsupportedOperationException( getClass().getName() + \" should only be used to bind null\" );\n\t\t\t}\n\t\t};\n\t}\n}\n","sourceCodeStart":53,"sourceCodeEnd":81,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/NullJdbcType.java#L53-L81","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nQuery q = em.createNativeQuery(\"select * from t where status = :p\");\nq.setParameter(\"p\", \"ACTIVE\"); // type inference falls back to NullJdbcType\n\n// after: bind with an explicit type\nq.setParameter(\"p\", \"ACTIVE\", String.class);","handlingStrategy":"validation","validationCode":"// Central typed binding helper prevents untyped parameters\nstatic <T> void bind(jakarta.persistence.Query q, String name, T value, Class<T> type) {\n    if (value != null) {\n        q.setParameter(name, value, type); // typed overload never resolves to NullJdbcType\n    } else {\n        q.setParameter(name, null, type);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    query.setParameter(\"p\", value).getResultList();\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"should only be used to bind null\")) {\n        // parameter had no resolvable JdbcType: rebind with setParameter(name, value, ExpectedType.class)\n    } else {\n        throw e;\n    }\n}","preventionTips":["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"],"tags":["hibernate","query-parameters","native-query","type-binding","null-type"],"backgroundTag":"missing-parameter-type","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}