hibernate/hibernate-orm · error · HibernateException
Unable to determine JDBC type for converted parameter relati
Error message
Unable to determine JDBC type for converted parameter relational type: " + relationalJavaType.getTypeName()
What it means
Thrown by ConverterHelper.createConvertedParameterType when building a BasicType for a query or procedure parameter that carries an explicit AttributeConverter. After constructing the JpaAttributeConverter, Hibernate looks up a standard basic type for the converter's relational (database-side) Java type; if none is registered, it cannot determine the JDBC type and fails.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ConverterHelper.java:80
Class<? extends AttributeConverter<X,Y>> converterClass,
ServiceRegistry serviceRegistry,
TypeConfiguration typeConfiguration) {
var converterBean = serviceRegistry.requireService( ManagedBeanRegistry.class ).getBean( converterClass );
return createJpaAttributeConverter( converterBean, typeConfiguration.getJavaTypeRegistry() );
}
public static <X> BasicType<X> createConvertedParameterType(
Class<? extends AttributeConverter<X,?>> converterClass,
ServiceRegistry serviceRegistry,
TypeConfiguration typeConfiguration) {
//noinspection unchecked,rawtypes
final JpaAttributeConverter<X,Object> converter =
createJpaAttributeConverter( (Class) converterClass, serviceRegistry, typeConfiguration );
final var relationalJavaType = converter.getRelationalJavaType();
final var relationalType =
typeConfiguration.standardBasicTypeForJavaType( relationalJavaType.getJavaTypeClass() );
if ( relationalType == null ) {
throw new HibernateException(
"Unable to determine JDBC type for converted parameter relational type: "
+ relationalJavaType.getTypeName()
);
}
return new ConvertedBasicTypeImpl<>(
"converted-parameter::" + converter.getConverterJavaType().getTypeName(),
String.format(
"BasicType adapter for converted query parameter AttributeConverter<%s,%s>",
converter.getDomainJavaType().getTypeName(),
relationalJavaType.getTypeName()
),
relationalType.getJdbcType(),
converter
);
}
}
View on GitHub (pinned to fad1729dce)
Solutions
- Change the converter's relational type to a standard basic type (String, Integer, Long, UUID, ...)
- If a custom relational type is required, register a JavaType and JdbcType for it (TypeContributor / @JavaTypeRegistration + @JdbcTypeRegistration)
- Drop the converter argument from setParameter and convert the value manually before binding
- Check for typos in the converter class passed to the parameter API
Example fix
// before
public class TagConverter implements AttributeConverter<Tag, TagCode> { ... }
query.setParameter("tag", tag, TagConverter.class); // TagCode is not a basic type
// after
public class TagConverter implements AttributeConverter<Tag, String> { ... }
query.setParameter("tag", tag, TagConverter.class); Defensive patterns
Strategy: validation
Validate before calling
// before binding a converter-typed parameter, assert the relational side is a basic type
TypeConfiguration tc = sessionFactory.getTypeConfiguration();
boolean ok = tc.standardBasicTypeForJavaType(TagCode.class) != null;
if (!ok) throw new IllegalArgumentException("Relational type of converter is not a basic type"); Type guard
static boolean converterHasBasicRelationalType(Class<? extends AttributeConverter<?, ?>> c) {
Type t = c.getGenericInterfaces()[0]; // AttributeConverter<D,R>
if (t instanceof ParameterizedType pt) {
Class<?> r = (Class<?>) pt.getActualTypeArguments()[1];
return Set.of(String.class, Integer.class, Long.class, Boolean.class,
java.math.BigDecimal.class, java.util.UUID.class, java.time.LocalDate.class)
.contains(r);
}
return false;
} Try / catch
try {
query.setParameter("tag", tag, TagConverter.class);
} catch (HibernateException e) {
// message contains 'Unable to determine JDBC type for converted parameter relational type'
throw new MappingException("Parameter converter " + TagConverter.class + " must target a basic relational type", e);
} Prevention
- Declare converters as AttributeConverter<Domain, String-or-Number> unless a custom type is registered
- Keep an architecture test (ArchUnit) that the 2nd type arg of every AttributeConverter is a basic type
- Register custom JavaType/JdbcType pairs before using them in parameter converters
- Prefer converting values manually for one-off native query parameters
When it happens
Trigger: Calling setParameter(name, value, MyConverter.class) on HQL/JPQL or native queries, criteriaBuilder.parameter(...) with a converter, or ProcedureCall parameter registration, where MyConverter's second type argument (the relational type) is not a known basic type (e.g. a custom class with no registered JavaType/JdbcType).
Common situations: Converter declared as AttributeConverter<Domain, CustomRelationalType> instead of AttributeConverter<Domain, String/Integer/...>; upgrading to Hibernate 6+ where the parameter-converter overload resolves types strictly; using a wrapper class (e.g. a record) as the relational side with no custom type registration.
Related errors
- Error attempting to apply AttributeConverter
- Error attempting to apply AttributeConverter: " + re.getMess
- Error attempting to apply AttributeConverter
- Error attempting to apply AttributeConverter: " + re.getMess
- Enum value converter returned null for enum class '" + enumC
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/4c5153fd06ed9004.
Report an issue: GitHub.