升级Grails 3.1至Hibernate 5.3适配MySQL8启动报错求助
问题背景
将Grails 3.1应用升级以适配MySQL 8,为使用MySQL8Dialect升级至Hibernate 5.3后,启动应用时出现以下报错:
ERROR org.springframework.boot.SpringApplication - Application startup failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceInitializedPublisher': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.context.ApplicationContext org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.applicationContext; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateDatastore': Cannot resolve reference to bean 'sessionFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.(Ljava/util/Collection;)V
用户已做的配置修改:
application.yml 修改
dataSource: driverClassName: com.mysql.cj.jdbc.Driver dialect: org.hibernate.dialect.MySQL8Dialect
build.gradle 修改
compile "org.grails.plugins:hibernate5" compile "org.hibernate:hibernate-core:5.3.34.Final" compile "org.hibernate:hibernate-ehcache:5.3.34.Final" runtime "mysql:mysql-connector-java:8.0.33"
问题原因
报错中的NoSuchMethodError是由于Grails 3.1默认的hibernate5插件版本与手动指定的Hibernate 5.3核心包存在版本冲突。Grails 3.1的hibernate5插件依赖特定版本的Hibernate核心库,强行手动指定更高版本的hibernate-core会导致类加载时方法签名不匹配:ClassLoaderServiceImpl的构造方法在不同Hibernate版本中发生了变化,旧版本插件代码调用了不存在的构造方法,最终抛出错误。
另外,Grails 3.1本身并不兼容Hibernate 5.3,该版本的Grails仅支持Hibernate 5.0/5.1系列,直接升级Hibernate核心版本会引发依赖不兼容问题。
解决方法
方案1:保留Grails 3.1版本,使用兼容的Hibernate版本
- 移除build.gradle中手动指定的
hibernate-core和hibernate-ehcache版本,让Grails的hibernate5插件自动管理依赖版本,避免冲突:
compile "org.grails.plugins:hibernate5" runtime "mysql:mysql-connector-java:8.0.33"
- 此时Hibernate版本会使用Grails 3.1兼容的5.0/5.1系列,虽然没有
MySQL8Dialect,但可以使用MySQL57Dialect替代,它同样支持MySQL 8的大部分特性,修改application.yml:
dataSource: driverClassName: com.mysql.cj.jdbc.Driver dialect: org.hibernate.dialect.MySQL57Dialect
方案2:升级Grails版本以兼容Hibernate 5.3
如果必须使用MySQL8Dialect,需要将Grails版本升级至3.3.x及以上,该版本开始支持Hibernate 5.3系列。升级后再配置Hibernate 5.3和MySQL 8驱动,此时版本冲突问题会自然解决。
内容的提问来源于stack exchange,提问作者Victor Soares

