hibernate/hibernate-orm · error · HibernateException
Could not create JdbcLiteralFormatter because UserType class
Error message
Could not create JdbcLiteralFormatter because UserType class '{}' did not implement EnhancedUserType What it means
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.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/internal/UserTypeJdbcTypeAdapter.java:89
@SuppressWarnings("unchecked")
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaType) {
assert javaType.getJavaTypeClass() == null
|| javaType.getJavaTypeClass().isAssignableFrom( this.javaType.getJavaTypeClass() );
return (ValueExtractor<X>) valueExtractor;
}
@Override
public JavaType<?> getRecommendedJavaType(
Integer length,
Integer scale,
TypeConfiguration typeConfiguration) {
return javaType;
}
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
if ( !( userType instanceof EnhancedUserType<?> ) ) {
throw new HibernateException( "Could not create JdbcLiteralFormatter because UserType class '"
+ userType.getClass().getName() + "' did not implement EnhancedUserType" );
}
final EnhancedUserType<T> type = (EnhancedUserType<T>) userType;
return (appender, value, dialect, wrapperOptions) ->
appender.append( type.toSqlLiteral( value ) );
}
private static class ValueExtractorImpl<J> implements ValueExtractor<J> {
private final UserType<J> userType;
public ValueExtractorImpl(UserType<J> userType) {
this.userType = userType;
}
@Override
public J extract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
final J extracted = userType.nullSafeGet( rs, paramIndex, options );
logExtracted( paramIndex, extracted );View on GitHub (pinned to fad1729dce)
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.
Example fix
// before - plain UserType: literal rendering throws HibernateException
public class IbanType implements UserType<Iban> { ... }
cb.equal( root.get( "iban" ), cb.literal( Iban.of( "DE89..." ) ) );
// after - EnhancedUserType renders the literal
public class IbanType implements UserType<Iban>, EnhancedUserType<Iban> {
@Override public String toSqlLiteral(Iban value) {
return "'" + value.text() + "'";
}
// ... existing UserType methods
} Defensive patterns
Strategy: type-guard
Validate before calling
// Before inlining literals of a custom type, verify literal support
if ( !( userType instanceof org.hibernate.usertype.EnhancedUserType<?> ) ) {
// bind the value as a parameter instead of a literal
query.setParameter( "v", value );
} else {
// literal rendering is safe (cb.literal(value), HQL literals)
} Type guard
static boolean rendersSqlLiteral(org.hibernate.usertype.UserType<?> userType) {
return userType instanceof org.hibernate.usertype.EnhancedUserType<?>;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No support for parsing UserType values from String: {}
- Named type [${typeImplementorClass}] did not implement Basic
- Error processing @TypeBinderType annotation '%s' for embedda
- Error processing @TypeBinderType annotation '%s' for entity
- error processing @AttributeBinderType annotation '%s' for at
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/c8fe31de0431fd52.
Report an issue: GitHub.