如何在使用Spring Boot 3.0.0-RC2进行AOT编译时包含PostgreSQL驱动程序

3

我编写了一个非常简单的服务,并尝试使用Graal VM作为本地可执行文件来运行它。该服务使用Spring Data和Postgres后端。以下插件包含在我的build.gradle配置中:

plugins {
   id 'java'
   id 'org.springframework.boot' version '3.0.0-RC2'
   id 'io.spring.dependency-management' version '1.1.0'
   id 'org.hibernate.orm' version '6.1.5.Final'
   id 'org.graalvm.buildtools.native' version '0.9.17'
}

我还包含了以下依赖项:

dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
   implementation 'org.springframework.boot:spring-boot-starter-validation'
   implementation 'org.springframework.boot:spring-boot-starter-web'
   runtimeOnly 'org.postgresql:postgresql'
   testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

我正在构建本地镜像以便它可以作为Docker容器执行:./gradlew bootBuildImage
当我尝试运行 Docker 镜像时,我会得到以下异常:
java.lang.NoSuchMethodException: org.postgresql.util.PGobject.<init>()
    at java.base@17.0.5/java.lang.Class.getConstructor0(DynamicHub.java:3585) ~[com.avisuite.airports.AirportsService:na]
    at java.base@17.0.5/java.lang.Class.getConstructor(DynamicHub.java:2271) ~[com.avisuite.airports.AirportsService:na]
    at org.hibernate.dialect.PostgreSQLPGObjectJdbcType.<clinit>(PostgreSQLPGObjectJdbcType.java:50) ~[com.avisuite.airports.AirportsService:6.1.5.Final]
    at org.hibernate.dialect.PostgreSQLDialect.registerColumnTypes(PostgreSQLDialect.java:231) ~[com.avisuite.airports.AirportsService:6.1.5.Final]
    at org.hibernate.dialect.Dialect.contributeTypes(Dialect.java:1341) ~[com.avisuite.airports.AirportsService:6.1.5.Final]
    at org.hibernate.dialect.PostgreSQLDialect.contributeTypes(PostgreSQLDialect.java:1229) ~[com.avisuite.airports.AirportsService:6.1.5.Final]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:386) ~[na:na]
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:143) ~[na:na]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1350) ~[com.avisuite.airports.AirportsService:6.1.5.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1421) ~[com.avisuite.airports.AirportsService:6.1.5.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) ~[na:na]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) ~[com.avisuite.airports.AirportsService:6.0.0-RC4]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[com.avisuite.airports.AirportsService:6.0.0-RC4]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[com.avisuite.airports.AirportsService:6.0.0-RC4]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) ~[com.avisuite.airports.AirportsService:6.0.0-RC4]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1799) ~[com.avisuite.airports.AirportsService:6.0.0-RC4]

我假设所需的PostgreSQL驱动程序类没有正确地打包为本地可执行文件的一部分。但是,我不确定如何继续以便包含它们。
编辑:
我将我的PostgreSQL依赖项从“runtimeOnly 'org.postgresql:postgresql'”更改为“aotRuntimeOnly 'org.postgresql:postgresql'”,现在我收到了不同的异常。
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataSourceScriptDatabaseInitializer': Unsatisfied dependency expressed through method 'dataSourceScriptDatabaseInitializer' parameter 0: Error creating bean with name 'dataSource': Instantiation of supplied bean failed
    at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArgument(BeanInstanceSupplier.java:351) ~[na:na]
    at org.springframework.beans.factory.aot.BeanInstanceSupplier.resolveArguments(BeanInstanceSupplier.java:271) ~[na:na]
    at org.springframework.beans.factory.aot.BeanInstanceSupplier.get(BeanInstanceSupplier.java:206) ~[na:na]
  

你能尝试像这样添加依赖项吗 -> compile group: 'org.postgresql', name: 'postgresql', version: 'versionNumber' 或者像这样 implementation 'org.postgresql:postgresql:versionNumber' - muhammed ozbilici
1个回答

2

异常是从PostgreSQLPGObjectJdbcType类中抛出的。

源代码指向需要注册一个类的位置:

ReflectHelper.classForName(
                    "org.postgresql.util.PGobject",
                    PostgreSQLPGObjectJdbcType.class
            );

你可以尝试添加自己的提示类 (https://www.baeldung.com/spring-native-intro#1-sample-jacksons-propertynamingstrategy):

@Configuration
@ImportRuntimeHints(NativeImageRuntimeHints.HibernateRegistrar.class)
public class NativeImageRuntimeHints {
    static class HibernateRegistrar implements RuntimeHintsRegistrar {
        @Override
        public void registerHints(org.springframework.aot.hint.RuntimeHints hints, ClassLoader classLoader) {
            try {
                hints.reflection()
                        .registerType(PGobject.class,
                                hint -> hint.withMembers(MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, MemberCategory.INTROSPECT_PUBLIC_METHODS)
                                        .onReachableType(PostgreSQLPGObjectJdbcType.class));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }
}

顺便提一下,Spring Boot 3.0.0 已经发布了。


我建议使用registerTypeIfPresent,如果您无法直接访问该类。 - user634545
您可以在此处阅读有关该问题的更多信息:https://github.com/spring-projects/spring-boot/issues/33400 - user634545

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接