Spring Boot 4构建Native Image时遭遇Hibernate插件兼容及运行时日志接口异常问题求助
Spring Boot 4构建Native Image时遭遇Hibernate插件兼容及运行时日志接口异常问题求助
大家好,我现在在尝试构建一个基于Spring Boot 4.0.0 + Spring Data JPA的项目,并编译为Native二进制文件,但过程中遇到了几个棘手的问题,想请教下社区的各位:
一、Hibernate版本与插件的兼容性疑问
Spring Boot 4.0.0默认集成的是Hibernate 7.1.8.Final,但我发现Maven中央仓库里并没有对应版本的org.hibernate.orm:hibernate-maven-plugin插件。无奈之下我手动把项目里的Hibernate版本升级到了7.1.9.Final和7.1.10.Final,但这里有个疑问:
- 这个
hibernate-maven-plugin在Spring Boot 3时代是必须的,但Spring Boot 4的迁移指南里完全没提到它,不过start.spring.io生成的JPA+Native项目里依然包含这个插件的配置。 - 现在Spring Boot 4环境下,我们还需要继续使用这个插件吗?
二、编译阶段的Hibernate类增强错误
解决了版本问题后,我执行./mvnw package进行编译,却遇到了类增强失败的错误,具体日志如下:
[ERROR] An exception occurred while trying to class file: /Users/edeandre/workspaces/quarkus/benchmarking/spring-quarkus-perf-comparison/springboot4/target/classes/org/acme/repository/FruitRepository.class org.hibernate.bytecode.enhance.spi.EnhancementException: Failed to enhance class org.acme.repository.FruitRepository at org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.enhance (EnhancerImpl.java:148) at org.hibernate.orm.tooling.maven.HibernateEnhancerMojo.enhanceClass (HibernateEnhancerMojo.java:235) at org.hibernate.orm.tooling.maven.HibernateEnhancerMojo.performEnhancement (HibernateEnhancerMojo.java:223) at org.hibernate.orm.tooling.maven.HibernateEnhancerMojo.execute (HibernateEnhancerMojo.java:99) at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126) at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328) at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174) at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75) at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162) at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39) at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:73) at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:53) at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:118) at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:261) at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:173) at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:101) at org.apache.maven.cli.MavenCli.execute (MavenCli.java:906) at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:283) at org.apache.maven.cli.MavenCli.main (MavenCli.java:206) at jdk.internal.reflect.DirectMethodHandleAccessor.invoke (DirectMethodHandleAccessor.java:104) at java.lang.reflect.Method.invoke (Method.java:565) at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:255) at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:201) at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:361) at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:314) Caused by: net.bytebuddy.pool.TypePool$Resolution$NoSuchTypeException: Cannot resolve type description for org.springframework.data.jpa.repository.JpaRepository at net.bytebuddy.pool.TypePool$Resolution$Illegal.resolve (TypePool.java:169) at net.bytebuddy.pool.TypePool$Default$LazyTypeDescription$TokenizedGenericType.toErasure (TypePool.java:7387) at net.bytebuddy.pool.TypePool$Default$LazyTypeDescription$TokenizedGenericType.asErasure (TypePool.java:7401) at org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.alreadyEnhanced (EnhancerImpl.java:668) at org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.doEnhance (EnhancerImpl.java:174) at org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.lambda$enhance$1 (EnhancerImpl.java:137) at org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState.rewrite (ByteBuddyState.java:175) at org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl.enhance (EnhancerImpl.java:137) ... 28 more
后来我尝试在hibernate-maven-plugin的配置里添加了Spring Data JPA的依赖,才绕过了这个错误:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>4.0.0</version> </dependency> </dependencies>
三、Native Image运行时的日志接口异常
绕过上一个问题后,Native Image成功编译,但启动项目并访问接口时,出现了日志接口找不到的运行时异常,导致请求失败,核心错误日志如下:
ERROR 31201 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: java.lang.ExceptionInInitializerError] with root cause java.lang.IllegalArgumentException: Invalid logger interface org.hibernate.engine.internal.NaturalIdLogging (implementation not found) at org.jboss.logging.Logger.doGetMessageLogger(Logger.java:2630) ~[springboot4:3.6.1.Final] at org.jboss.logging.Logger.getMessageLogger(Logger.java:2536) ~[springboot4:3.6.1.Final] at org.jboss.logging.Logger.getMessageLogger(Logger.java:2521) ~[springboot4:3.6.1.Final] at org.hibernate.engine.internal.NaturalIdLogging.<clinit>(NaturalIdLogging.java:36) ~[na:na] at org.hibernate.engine.internal.NaturalIdResolutionsImpl.cacheResolutionFromLoad(NaturalIdResolutionsImpl.java:72) ~[na:na] at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.registerNaturalIdResolution(EntityInitializerImpl.java:1633) ~[na:na] at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.initializeEntityInstance(EntityInitializerImpl.java:1584) ~[na:na] at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.initializeInstance(EntityInitializerImpl.java:1464) ~[na:na] at org.hibernate.sql.results.graph.entity.internal.EntityInitializerImpl.initializeInstance(EntityInitializerImpl.java:98) ~[na:na] at org.hibernate.sql.results.internal.StandardRowReader.coordinateInitializers(StandardRowReader.java:239) ~[na:na] at org.hibernate.sql.results.internal.StandardRowReader.readRow(StandardRowReader.java:136) ~[na:na] at org.hibernate.sql.results.spi.ListResultsConsumer.read(ListResultsConsumer.java:245) ~[springboot4:7.1.9.Final] at org.hibernate.sql.results.spi.ListResultsConsumer.readRows(ListResultsConsumer.java:235) ~[springboot4:7.1.9.Final] at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:166) ~[springboot4:7.1.9.Final] at org.hibernate.sql.results.spi.ListResultsConsumer.consume(ListResultsConsumer.java:33) ~[springboot4:7.1.9.Final] at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.doExecuteQuery(JdbcSelectExecutorStandardImpl.java:201) ~[na:na] at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.executeQuery(JdbcSelectExecutorStandardImpl.java:100) ~[na:na] at org.hibernate.sql.exec.spi.JdbcSelectExecutor.executeQuery(JdbcSelectExecutor.java:64) ~[springboot4:7.1.9.Final] at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:138) ~[springboot4:7.1.9.Final] at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.lambda$new$1(ConcreteSqmSelectQueryPlan.java:146) ~[na:na] at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:455) ~[na:na] at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:388) ~[na:na] at org.hibernate.query.sqm.internal.SqmQueryImpl.doList(SqmQueryImpl.java:386) ~[na:na] at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:154) ~[springboot4:7.1.9.Final] at org.hibernate.query.Query.getResultList(Query.java:121) ~[springboot4:7.1.9.Final] at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:414) ~[springboot4:4.0.0] at java.base@25/java.lang.reflect.Method.invoke(Method.java:565) ~[springboot4:na] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359) ~[na:na] at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:278) ~[na:na] at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:169) ~[springboot4:4.0.0] at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158) ~[springboot4:4.0.0] at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:545) ~[springboot4:4.0.0] at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:290) ~[springboot4:4.0.0] at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:708) ~[springboot4:4.0.0] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[na:na] at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:171) ~[na:na] at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:146) ~[na:na] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[na:na] at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:69) ~[na:na] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[na:na] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:370) ~[springboot4:7.0.1] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118) ~[springboot4:7.0.1] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[na:na] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:135) ~[na:na] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[na:na] at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:166) ~[na:na] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[na:na] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:222) ~[na:na] at jdk.proxy4/jdk.proxy4.$Proxy/s8244dec2.findAll(Unknown Source) ~[na:na] at org.acme.rest.FruitController.getAll(FruitController.java:31) ~[springboot4:na] at java.base@25/java.lang.reflect.Method.invoke(Method.java:565) ~[springboot4:na] at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359) ~[na:na] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:715) ~[na:na] at org.acme.rest.FruitController$$SpringCGLIB$$0.getAll(<generated>) ~[springboot4:na] at java.base@25/java.lang.reflect.Method.invoke(Method.java:565) ~[springboot4:na] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) ~[springboot4:7.0.1] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:190) ~[springboot4:7.0.1] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[springboot4:7.0.1] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:934) ~[springboot4:7.0.1] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:853) ~[springboot4:7.0.1] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:86) ~[springboot4:7.0.1] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) ~[springboot4:7.0.1] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:866) ~[springboot4:7.0.1] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1003) ~[springboot4:7.0.1] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:892) ~[springboot4:7.0.1] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[springboot4:6.1] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:874) ~[springboot4:7.0.1] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710) ~[springboot4:6.1] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:128) ~[na:na] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[springboot4:11.0.14] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:




