{"record":{"id":"4c5153fd06ed9004","repo":"hibernate/hibernate-orm","slug":"unable-to-determine-jdbc-type-for-converted-parame","errorCode":null,"errorMessage":"Unable to determine JDBC type for converted parameter relational type: \" + relationalJavaType.getTypeName()","messagePattern":"Unable to determine JDBC type for converted parameter relational type: \" \\+ relationalJavaType\\.getTypeName\\(\\)","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ConverterHelper.java","lineNumber":80,"sourceCode":"\t\t\tClass<? extends AttributeConverter<X,Y>> converterClass,\n\t\t\tServiceRegistry serviceRegistry,\n\t\t\tTypeConfiguration typeConfiguration) {\n\t\tvar converterBean = serviceRegistry.requireService( ManagedBeanRegistry.class ).getBean( converterClass );\n\t\treturn createJpaAttributeConverter( converterBean, typeConfiguration.getJavaTypeRegistry() );\n\t}\n\n\tpublic static <X> BasicType<X> createConvertedParameterType(\n\t\t\tClass<? extends AttributeConverter<X,?>> converterClass,\n\t\t\tServiceRegistry serviceRegistry,\n\t\t\tTypeConfiguration typeConfiguration) {\n\t\t//noinspection unchecked,rawtypes\n\t\tfinal JpaAttributeConverter<X,Object> converter =\n\t\t\t\tcreateJpaAttributeConverter( (Class) converterClass, serviceRegistry, typeConfiguration );\n\t\tfinal var relationalJavaType = converter.getRelationalJavaType();\n\t\tfinal var relationalType =\n\t\t\t\ttypeConfiguration.standardBasicTypeForJavaType( relationalJavaType.getJavaTypeClass() );\n\t\tif ( relationalType == null ) {\n\t\t\tthrow new HibernateException(\n\t\t\t\t\t\"Unable to determine JDBC type for converted parameter relational type: \"\n\t\t\t\t\t\t\t+ relationalJavaType.getTypeName()\n\t\t\t);\n\t\t}\n\t\treturn new ConvertedBasicTypeImpl<>(\n\t\t\t\t\"converted-parameter::\" + converter.getConverterJavaType().getTypeName(),\n\t\t\t\tString.format(\n\t\t\t\t\t\t\"BasicType adapter for converted query parameter AttributeConverter<%s,%s>\",\n\t\t\t\t\t\tconverter.getDomainJavaType().getTypeName(),\n\t\t\t\t\t\trelationalJavaType.getTypeName()\n\t\t\t\t),\n\t\t\t\trelationalType.getJdbcType(),\n\t\t\t\tconverter\n\t\t);\n\t}\n}\n","sourceCodeStart":62,"sourceCodeEnd":97,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/converter/internal/ConverterHelper.java#L62-L97","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\npublic class TagConverter implements AttributeConverter<Tag, TagCode> { ... }\nquery.setParameter(\"tag\", tag, TagConverter.class); // TagCode is not a basic type\n// after\npublic class TagConverter implements AttributeConverter<Tag, String> { ... }\nquery.setParameter(\"tag\", tag, TagConverter.class);","handlingStrategy":"validation","validationCode":"// before binding a converter-typed parameter, assert the relational side is a basic type\nTypeConfiguration tc = sessionFactory.getTypeConfiguration();\nboolean ok = tc.standardBasicTypeForJavaType(TagCode.class) != null;\nif (!ok) throw new IllegalArgumentException(\"Relational type of converter is not a basic type\");","typeGuard":"static boolean converterHasBasicRelationalType(Class<? extends AttributeConverter<?, ?>> c) {\n    Type t = c.getGenericInterfaces()[0]; // AttributeConverter<D,R>\n    if (t instanceof ParameterizedType pt) {\n        Class<?> r = (Class<?>) pt.getActualTypeArguments()[1];\n        return Set.of(String.class, Integer.class, Long.class, Boolean.class,\n                java.math.BigDecimal.class, java.util.UUID.class, java.time.LocalDate.class)\n              .contains(r);\n    }\n    return false;\n}","tryCatchPattern":"try {\n    query.setParameter(\"tag\", tag, TagConverter.class);\n} catch (HibernateException e) {\n    // message contains 'Unable to determine JDBC type for converted parameter relational type'\n    throw new MappingException(\"Parameter converter \" + TagConverter.class + \" must target a basic relational type\", e);\n}","preventionTips":["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"],"tags":["hibernate","orm","jpa","attribute-converter","query-parameters","type-mapping"],"backgroundTag":"no-jdbc-type-for-java-type","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}