{"record":{"id":"c8fe31de0431fd52","repo":"hibernate/hibernate-orm","slug":"could-not-create-jdbcliteralformatter-because-user","errorCode":null,"errorMessage":"Could not create JdbcLiteralFormatter because UserType class '{}' did not implement EnhancedUserType","messagePattern":"Could not create JdbcLiteralFormatter because UserType class '(.+?)' did not implement EnhancedUserType","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/internal/UserTypeJdbcTypeAdapter.java","lineNumber":89,"sourceCode":"\t@SuppressWarnings(\"unchecked\")\n\tpublic <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {\n\t\tassert javaType.getJavaTypeClass() == null\n\t\t\t\t|| javaType.getJavaTypeClass().isAssignableFrom( this.javaType.getJavaTypeClass() );\n\t\treturn (ValueExtractor<X>) valueExtractor;\n\t}\n\n\t@Override\n\tpublic JavaType<?> getRecommendedJavaType(\n\t\t\tInteger length,\n\t\t\tInteger scale,\n\t\t\tTypeConfiguration typeConfiguration) {\n\t\treturn javaType;\n\t}\n\n\t@Override\n\tpublic <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {\n\t\tif ( !( userType instanceof EnhancedUserType<?> ) ) {\n\t\t\tthrow new HibernateException( \"Could not create JdbcLiteralFormatter because UserType class '\"\n\t\t\t\t\t\t\t+ userType.getClass().getName() + \"' did not implement EnhancedUserType\" );\n\t\t}\n\t\tfinal EnhancedUserType<T> type = (EnhancedUserType<T>) userType;\n\t\treturn (appender, value, dialect, wrapperOptions) ->\n\t\t\t\tappender.append( type.toSqlLiteral( value ) );\n\t}\n\n\tprivate static class ValueExtractorImpl<J> implements ValueExtractor<J> {\n\t\tprivate final UserType<J> userType;\n\n\t\tpublic ValueExtractorImpl(UserType<J> userType) {\n\t\t\tthis.userType = userType;\n\t\t}\n\n\t\t@Override\n\t\tpublic J extract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {\n\t\t\tfinal J extracted = userType.nullSafeGet( rs, paramIndex, options );\n\t\t\tlogExtracted( paramIndex, extracted );","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/internal/UserTypeJdbcTypeAdapter.java#L71-L107","documentation":"UserTypeJdbcTypeAdapter bridges a UserType to Hibernate's JdbcType SPI; getJdbcLiteralFormatter (UserTypeJdbcTypeAdapter.java:85-93) must render values of the type as inline SQL literals, and it can only do that through EnhancedUserType.toSqlLiteral. If the user type does not implement EnhancedUserType, this HibernateException is thrown the first time Hibernate needs to inline such a value into SQL.","triggerScenarios":"Rendering a literal for a UserType-mapped value into generated SQL: criteria queries using CriteriaBuilder.literal(value) on such a type, HQL literals compared against a UserType-mapped attribute, and query/dialect paths that inline parameters as literals; all fail unless the UserType implements EnhancedUserType.","commonSituations":"Long-standing plain UserTypes surviving an ORM upgrade that renders literals more eagerly; generated query code that inlines constants; dialects or settings (literal handling) that favor inlined literals over bind parameters.","solutions":["Implement EnhancedUserType<J> on the user type and provide toSqlLiteral(J) returning the dialect-safe literal text (quoted for strings).","Avoid inlining: pass the value as a bound parameter (setParameter) instead of a literal where possible.","Replace the UserType with an AttributeConverter over a standard basic type, which gets literal formatting for free."],"exampleFix":"// before - plain UserType: literal rendering throws HibernateException\npublic class IbanType implements UserType<Iban> { ... }\ncb.equal( root.get( \"iban\" ), cb.literal( Iban.of( \"DE89...\" ) ) );\n\n// after - EnhancedUserType renders the literal\npublic class IbanType implements UserType<Iban>, EnhancedUserType<Iban> {\n    @Override public String toSqlLiteral(Iban value) {\n        return \"'\" + value.text() + \"'\";\n    }\n    // ... existing UserType methods\n}","handlingStrategy":"type-guard","validationCode":"// Before inlining literals of a custom type, verify literal support\nif ( !( userType instanceof org.hibernate.usertype.EnhancedUserType<?> ) ) {\n    // bind the value as a parameter instead of a literal\n    query.setParameter( \"v\", value );\n} else {\n    // literal rendering is safe (cb.literal(value), HQL literals)\n}","typeGuard":"static boolean rendersSqlLiteral(org.hibernate.usertype.UserType<?> userType) {\n    return userType instanceof org.hibernate.usertype.EnhancedUserType<?>;\n}","tryCatchPattern":null,"preventionTips":["Default to bound parameters (setParameter) instead of cb.literal for custom-typed values.","When writing a UserType, implement EnhancedUserType.toSqlLiteral defensively.","Unit-test generated SQL for queries containing literals of custom types."],"tags":["hibernate","usertype","custom-type","sql-literal","query-generation"],"backgroundTag":"custom-type-sql-literal-unsupported","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}