Quarkus 3迁移时出现org.hibernate.mapping.BasicValue转ToOne类型转换错误
Quarkus v3.1.1.FINAL 迁移时Hibernate实体映射启动错误问题
我们正将Quarkus应用从v2版本迁移至v3.1.1.FINAL版本,在实体关系映射场景下遇到启动错误。
实体映射代码
Library实体
@Entity @Data public class Library { @Id Long id; String name; @OneToMany(mappedBy = "libraryId") List<Book> books; }
Book实体
@Data @Entity public class Book { @Id Long id; Long libraryId; String name; @ManyToOne @JoinColumn(name = "library_id") Library library; }
启动错误日志
2023-06-12 10:09:05,666 ERROR [io.qua.run.boo.StartupActionImpl] (Quarkus Main Thread) Error running Quarkus: java.lang.reflect.InvocationTargetException 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) Caused by: java.lang.ExceptionInInitializerError 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) ... 6 more Caused by: java.lang.RuntimeException: Failed to start quarkus at io.quarkus.runner.ApplicationImpl.<clinit>(Unknown Source) ... 15 more Caused by: java.lang.ClassCastException: class org.hibernate.mapping.BasicValue cannot be cast to class org.hibernate.mapping.ToOne (org.hibernate.mapping.BasicValue and org.hibernate.mapping.ToOne are in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @ef9296d) at org.hibernate.boot.model.internal.BinderHelper.checkMappedByType(BinderHelper.java:1086) at org.hibernate.boot.model.internal.CollectionBinder.isReversePropertyInJoin(CollectionBinder.java:1571) at org.hibernate.boot.model.internal.CollectionBinder.noAssociationTable(CollectionBinder.java:1582) at org.hibernate.boot.model.internal.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:1543) at org.hibernate.boot.model.internal.CollectionBinder$1.secondPass(CollectionBinder.java:1534) at org.hibernate.boot.model.internal.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:45) at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1857) at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1814) 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) ... 16 more
我们提供了包含完整依赖树的复现项目,项目内的tree.txt文件记录了所有依赖信息。
问题原因与解决方案
问题根源
@OneToMany注解的mappedBy属性配置错误:该属性应该指向关联实体(Book)中对应的实体对象属性,而非基本类型的外键字段。Quarkus v3.x升级了Hibernate ORM至6.x版本,对映射规则的校验更加严格,旧版本中可能容忍的错误配置在新版本中直接触发类型转换异常。
修复步骤
- 修正
Library实体的@OneToMany映射:将mappedBy的值从libraryId改为library,对应Book实体中的关联实体属性。 - (推荐)移除冗余的外键字段:删除Book实体中的
Long libraryId字段,Hibernate会通过@ManyToOne的library属性自动映射library_id数据库字段,手动维护基本类型外键易引发数据不一致问题。
修复后的实体代码
Library实体
@Entity @Data public class Library { @Id Long id; String name; @OneToMany(mappedBy = "library") List<Book> books; }
Book实体
@Data @Entity public class Book { @Id Long id; String name; @ManyToOne @JoinColumn(name = "library_id") Library library; }
内容的提问来源于stack exchange,提问作者Hassan Nazar
相关产品推荐
相关产品推荐

