{"record":{"id":"61aae558d818e69d","repo":"hibernate/hibernate-orm","slug":"could-not-determine-recommended-jdbctype-for-61aae5","errorCode":null,"errorMessage":"Could not determine recommended JdbcType for '\" + getTypeName() + \"'\"","messagePattern":"Could not determine recommended JdbcType for '\" \\+ getTypeName\\(\\) \\+ \"'\"","errorType":"exception","errorClass":"JdbcTypeRecommendationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeBasicAdaptor.java","lineNumber":30,"sourceCode":"\n/**\n * {@link AbstractClassJavaType} for cases where we do not know a proper\n * {@link org.hibernate.type.descriptor.java.JavaType} for a given Java type.\n *\n * @author Steve Ebersole\n */\npublic class JavaTypeBasicAdaptor<T> extends AbstractClassJavaType<T> {\n\tpublic JavaTypeBasicAdaptor(Class<T> type) {\n\t\tsuper( type );\n\t}\n\n\tpublic JavaTypeBasicAdaptor(Class<T> type, MutabilityPlan<T> mutabilityPlan) {\n\t\tsuper( type, mutabilityPlan );\n\t}\n\n\t@Override\n\tpublic JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) {\n\t\tthrow new JdbcTypeRecommendationException(\n\t\t\t\t\"Could not determine recommended JdbcType for '\" + getTypeName() + \"'\"\n\t\t);\n\t}\n\n\t@Override\n\tpublic boolean useObjectEqualsHashCode() {\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic <X> X unwrap(T value, Class<X> type, WrapperOptions options) {\n\t\tthrow new UnsupportedOperationException(\n\t\t\t\t\"Unwrap strategy not known for this Java type: \" + getTypeName()\n\t\t);\n\t}\n\n\t@Override\n\tpublic <X> T wrap(X value, WrapperOptions options) {","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeBasicAdaptor.java#L12-L48","documentation":"JavaTypeBasicAdaptor is a bare fallback JavaType: it describes a Java class to Hibernate with no JDBC knowledge at all. Whenever mapping requests a recommended JdbcType from it — an attribute of that class with no @JdbcType/@JdbcTypeCode and no complete BasicType registered — bootstrap fails with JdbcTypeRecommendationException.","triggerScenarios":"Registering only a JavaType for a class (@JavaType, JavaTypeRegistry.addDescriptor) and mapping an attribute of that class without any JDBC-side annotation; DDL export or schema validation asking for the default SQL type of such an attribute.","commonSituations":"Custom value objects expected to 'just work' as basic types; partial registrations copied from hibernate-types-style integrations; annotating @JavaType while forgetting that a JavaType alone never defines storage.","solutions":["Add the JDBC half: @JdbcType or @JdbcTypeCode on the attribute","Register a complete BasicType (JavaType + JdbcType) via @TypeRegistration instead of a bare JavaType","Or add an AttributeConverter to a supported basic type (String/Long/...), which supplies the JDBC side implicitly"],"exampleFix":"// before\n@JavaType(MoneyJavaType.class)\nMoney price; // adaptor has no recommended JDBC type -> throws at boot\n\n// after\n@JavaType(MoneyJavaType.class)\n@JdbcTypeCode(SqlTypes.NUMERIC)\nMoney price;","handlingStrategy":"validation","validationCode":"static List<String> incompleteTypeMappings(Class<?> entity) {\n    var bad = new ArrayList<String>();\n    for (var f : entity.getDeclaredFields()) {\n        boolean needsJdbc = f.isAnnotationPresent(org.hibernate.annotations.JavaType.class);\n        boolean hasJdbc = f.isAnnotationPresent(org.hibernate.annotations.JdbcType.class)\n            || f.isAnnotationPresent(org.hibernate.annotations.JdbcTypeCode.class)\n            || f.isAnnotationPresent(jakarta.persistence.Convert.class)\n            || f.isAnnotationPresent(org.hibernate.annotations.Type.class);\n        if (needsJdbc && !hasJdbc) bad.add(entity.getSimpleName() + \".\" + f.getName());\n    }\n    return bad;\n}","typeGuard":null,"tryCatchPattern":"try {\n    metadata.buildSessionFactory();\n} catch (org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException e) {\n    // add @JdbcType/@JdbcTypeCode to the field for the type named in the message, then rebuild\n}","preventionTips":["A JavaType alone never defines storage — always pair it with a JdbcType or converter","Prefer @TypeRegistration of complete BasicTypes","Run schema export in CI to surface missing JDBC types before deploy"],"tags":["hibernate","orm","jdbc-type","custom-type","bootstrap"],"backgroundTag":"jdbc-type-resolution-failure","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}