postgresql - 如何使用spring boot 3.0.0-RC2在spring AOT编译中包含postgres驱动

标签 postgresql spring-boot spring-data-jpa

我已经编写了一个非常简单的服务,我正在尝试使用 Graal VM 作为 native 可执行文件运行。该服务使用带有 Postgres 后端的 spring 数据。以下插件包含在我的 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'
}

我正在构建一个 native 镜像,以便它可以作为 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]

我假设所需的 postgres 驱动程序类未正确打包为 native 可执行文件的一部分。但是,我不确定如何继续以包含它们。

编辑:

我将我的 postgres 依赖项从 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]
  

最佳答案

异常是从 PostgreSQLPGObjectJdbcType 类抛出的。

源代码指向您注册类(class)所需的内容:

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 已经发布。

关于postgresql - 如何使用spring boot 3.0.0-RC2在spring AOT编译中包含postgres驱动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74581603/

相关文章:

java - Spring Data Predicate - 在子集合中搜索属性

java - 无法使用可嵌入 ID 创建新实体

json - PostgreSQL引入JSONB的解释

java - 如何使用 Junit 配置 Spring Boot 的按测试方法实例化?

java - Google云端硬盘API-Drive.Files类没有insert()方法

java - 如何使用限定符来决定类的字段?

java - 如何避免 javax.persistence.EntityExistsException : different object with the same identifier?

java - 之前使用data.sql导入数据时无法使用save()插入

postgresql - PGSQL JSONB 中带有部分路径的深度 JSON 查询?

sql - 检查 Postgres 上的外部表所有者