You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迁移至Quarkus+Hibernate:如何定位PersonBO的JdbcType推荐异常

从Payara+EclipseLink迁移到Quarkus(Hibernate)启动异常排查

问题背景

将应用从Payara + EclipseLink迁移至Quarkus(使用Hibernate)时,启动阶段Hibernate抛出如下异常:

JdbcTypeRecommendationException
Failed to start quarkus: io.quarkus.dev.appstate.ApplicationStartException:
org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException:
Could not determine recommended JdbcType for Entity

该应用在EclipseLink环境下运行正常。已为PostgreSQL中所有对应JSONB列的属性添加Hibernate专属注解@JdbcTypeCode(SqlTypes.JSON),且已知错误可能来自关联对象,但关联对象数量较多,难以逐一排查。

疑问

  1. 能否让Hibernate明确指出触发异常的具体类和属性?
  2. Hibernate强制要求给PersonBO添加@DiscriminatorValue(value = "P")注解,但EclipseLink和JPA 2.2均无此要求,该问题是否与启动异常相关?

相关实体代码

PersonBO 实体类

@Entity
@Access(AccessType.PROPERTY)
@Table(name = PersonBO.TABLENAME)
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.CHAR, name = "prssubclass")
@DiscriminatorValue(value = "P")
public class PersonBO {

    /** Name of this database table is {@value} */
    final public static String TABLENAME = "person";

    // --- Database columns
    private UUID id = UUID.randomUUID();
    private List<AddressGeoBO> adrGeos = null;
    private Map<String, Object> prsAttributes = null;
    private Gender prsGender = null;
    private Set<UUID> tags = null;

    @Convert(converter = UuidConverter4jpa.class)
    @GeneratedValue(strategy = GenerationType.UUID)
    @Id
    public UUID getId() { return id; }

    @Json
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER,
            mappedBy = AddressGeoBO.FIELD_PERSONBO,
            targetEntity = AddressGeoBO.class, orphanRemoval = true)
    public List<AddressGeoBO> getAdrGeos() { return adrGeos; }

    @Convert(converter = JsonMapConverter4jpa.class)
    @JdbcTypeCode(SqlTypes.JSON)
    @Json
    public Map<String, Object> getPrsAttributes() { return this.prsAttributes; }

    @Convert(converter = Gender.Converter4jpa.class)
    @Json(converter = Gender.Converter4json.class)
    public Gender getPrsGender() { return this.prsGender; }

    @Convert(converter = JsonSetUuidConverter4jpa.class)
    @JdbcTypeCode(SqlTypes.JSON)
    @Json
    public Set<UUID> getTags() { return tags; }
}

AddressGeoBO 关联实体类

@Entity
@Access(AccessType.PROPERTY)
@Table(name = AddressGeoBO.TABLENAME)
public class AddressGeoBO {
    final public static String TABLENAME = "addressgeo";
    private UUID id = UUID.randomUUID();
    private PersonBO personBO = null;

    @JoinColumn(name = "personId", referencedColumnName = "id")
    @ManyToOne(targetEntity = PersonBO.class)
    public PersonBO getPersonBO() { return this.personBO; }
}

PersonBO 子类 IdentityBO

@Entity
@Access(AccessType.PROPERTY)
@Table(name = "identity")
@DiscriminatorValue(value = "I")
public class IdentityBO extends PersonBO { ... }

完整启动堆栈信息

2023-09-24 15:40:20,279 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (main) Failed to start quarkus: io.quarkus.dev.appstate.ApplicationStartException: org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException: Could not determine recommended JdbcType for `com.djarjo.person.PersonBO`
    at io.quarkus.dev.appstate.ApplicationStateNotification.waitForApplicationStart(ApplicationStateNotification.java:58)
    at io.quarkus.runner.bootstrap.StartupActionImpl.runMainClass(StartupActionImpl.java:123)
    at io.quarkus.deployment.dev.IsolatedDevModeMain.firstStart(IsolatedDevModeMain.java:113)
    at io.quarkus.deployment.dev.IsolatedDevModeMain.accept(IsolatedDevModeMain.java:423)
    at io.quarkus.deployment.dev.IsolatedDevModeMain.accept(IsolatedDevModeMain.java:55)
    at io.quarkus.bootstrap.app.CuratedApplication.runInCl(CuratedApplication.java:138)
    at io.quarkus.bootstrap.app.CuratedApplication.runInAugmentClassLoader(CuratedApplication.java:93)
    at io.quarkus.deployment.dev.DevModeMain.start(DevModeMain.java:131)
    at io.quarkus.deployment.dev.DevModeMain.main(DevModeMain.java:62)
Caused by: org.hibernate.type.descriptor.java.spi.JdbcTypeRecommendationException: Could not determine recommended JdbcType for `com.djarjo.person.PersonBO`
    at org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType.getRecommendedJdbcType(UnknownBasicJavaType.java:37)
    at org.hibernate.boot.model.process.internal.InferredBasicValueResolver.from(InferredBasicValueResolver.java:222)
    at org.hibernate.mapping.BasicValue.buildResolution(BasicValue.java:480)
    at org.hibernate.mapping.BasicValue.resolve(BasicValue.java:310)
    at org.hibernate.mapping.BasicValue.resolve(BasicValue.java:300)
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.lambda$processValueResolvers$4(InFlightMetadataCollectorImpl.java:1842)
    at java.base/java.util.ArrayList.removeIf(ArrayList.java:1682)
    at java.base/java.util.ArrayList.removeIf(ArrayList.java:1660)
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processValueResolvers(InFlightMetadataCollectorImpl.java:1841)
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1827)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:328)
    at io.quarkus.hibernate.orm.runtime.boot.FastBootMetadataBuilder.build(FastBootMetadataBuilder.java:406)
    at io.quarkus.hibernate.orm.runtime.PersistenceUnitsHolder.createMetadata(PersistenceUnitsHolder.java:101)
    at io.quarkus.hibernate.orm.runtime.PersistenceUnitsHolder.constructMetadataAdvance(PersistenceUnitsHolder.java:73)
    at io.quarkus.hibernate.orm.runtime.PersistenceUnitsHolder.initializeJpa(PersistenceUnitsHolder.java:40)
    at io.quarkus.hibernate.orm.runtime.HibernateOrmRecorder$1.created(HibernateOrmRecorder.java:78)
    at io.quarkus.arc.runtime.ArcRecorder.initBeanContainer(ArcRecorder.java:79)
    at io.quarkus.deployment.steps.ArcProcessor$generateResources844392269.deploy_0(Unknown Source)
    at io.quarkus.deployment.steps.ArcProcessor$generateResources844392269.deploy(Unknown Source)
    at io.quarkus.runner.ApplicationImpl.<clinit>(Unknown Source)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at io.quarkus.runtime.Quarkus.run(Quarkus.java:70)
    at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
    at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
    at io.quarkus.runner.GeneratedMain.main(Unknown Source)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at io.quarkus.runner.bootstrap.StartupActionImpl$1.run(StartupActionImpl.java:104)
    at java.base/java.lang.Thread.run(Thread.java:833)

问题分析与解决

1. 定位报错具体位置

  • 启用Hibernate DEBUG日志,在application.properties中添加:
    quarkus.log.category."org.hibernate.boot.model.process.internal".level=DEBUG
    
    启动后,DEBUG日志会输出Hibernate处理每个属性的过程,可从中定位未正确映射的属性。
  • 逐步注释关联实体或复杂属性,逐个排查缩小范围。

2. @DiscriminatorValue与异常的关联

该注解要求与启动异常无关。Hibernate对JOINED继承策略的处理更严格,要求父类显式指定@DiscriminatorValue,而EclipseLink允许隐式默认值,这只是JPA实现间的差异,不会导致JdbcType推荐异常。

3. 核心问题排查

从堆栈看,Hibernate将PersonBO识别为基本类型而非实体类型,根源可能是:

  • 某实体中存在PersonBO类型属性,但未添加@ManyToOne/@OneToOne等关联注解,导致Hibernate尝试将其作为基本类型映射。
  • 检查所有使用PersonBO作为属性的类,确保关联注解配置正确。
  • 排查自定义Converter是否错误处理了PersonBO类型,混淆了Hibernate的类型映射逻辑。

内容的提问来源于stack exchange,提问作者Jemolah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 11:54:54