Postgres 的 Springboot application.properties 不起作用 - 致命:数据库“null”不存在

问题描述 投票:0回答:1

我遇到的问题是Springboot版本:1.5.9.RELEASE的自动配置似乎不起作用。

注意,如果我定义一个返回 DataSource bean 的 bean,我可能能够克服当前的问题。

DataSource bean 可能看起来非常类似于: 以下片段中的示例: https://www.atomikos.com/Documentation/ConfiguringPostgreSQL

我正在切换 application.properties 配置以停止使用 Spring Boot 使用的默认 H2 数据库并将其切换到 postgres。

下页所示的配置片段: https://dzone.com/articles/configuring-spring-boot-for-postgresql

肯定不行。 这是我的配置:

spring.datasource.url=jdbc:postgresql://localhost:5432/dummydb
spring.datasource.username=DUMMYDB
spring.datasource.password=DUMMYDB
spring.jpa.hibernate.ddl-auto=create-drop

这不起作用,为什么? 显然是出于一个非常简单的原因。 虽然用户名和密码肯定是有用的,并且在连接工厂尝试为数据库建立连接时会被传输。 URL 属性在配置数据源时没有用处。

首先让我给您提供最终的堆栈跟踪:

Caused by: org.postgresql.util.PSQLException: FATAL: database "null" does not exist
    at org.postgresql.core.v3.ConnectionFactoryImpl.readStartupMessages(ConnectionFactoryImpl.java:469) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:112) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:125) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:30) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.jdbc3g.AbstractJdbc3gConnection.<init>(AbstractJdbc3gConnection.java:22) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.jdbc4.AbstractJdbc4Connection.<init>(AbstractJdbc4Connection.java:30) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.jdbc4.Jdbc4Connection.<init>(Jdbc4Connection.java:24) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.Driver.makeConnection(Driver.java:393) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.Driver.connect(Driver.java:267) ~[postgresql-9.1-901.jdbc4.jar:na]
    at java.sql.DriverManager.getConnection(DriverManager.java:664) ~[na:1.8.0_112]
    at java.sql.DriverManager.getConnection(DriverManager.java:247) ~[na:1.8.0_112]
    at org.postgresql.ds.common.BaseDataSource.getConnection(BaseDataSource.java:91) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.xa.PGXADataSource.getXAConnection(PGXADataSource.java:47) ~[postgresql-9.1-901.jdbc4.jar:na]
    at org.postgresql.xa.PGXADataSource.getXAConnection(PGXADataSource.java:32) ~[postgresql-9.1-901.jdbc4.jar:na]
    at com.atomikos.jdbc.AtomikosXAConnectionFactory.createPooledConnection(AtomikosXAConnectionFactory.java:60) ~[transactions-jdbc-3.9.3.jar:na]
    ... 44 common frames omitted

为什么这不起作用是因为 postgres 基础数据源根本不关心通过 URL 进行配置。 相反,它希望通过传递的 setter 进行配置: 数据库名称、端口等... 请看下面的课程:

org.postgresql.ds.common.BaseDataSource

该类提供了多个setter。对于用户名,密码等等。 但没有 URL 的 setter。组成 URL 的各个元素(例如数据库名称)需要进入专用字段。

因此,该类提供的是 getURL() 方法,该方法重新调整数据库为 null 的奇怪 URL。 这是该方法的代码片段。

/**
     * Generates a DriverManager URL from the other properties supplied.
     */
    private String getUrl()
    {
        StringBuffer sb = new StringBuffer(100);
        sb.append("jdbc:postgresql://");
        sb.append(serverName);
        if (portNumber != 0) {
            sb.append(":").append(portNumber);
        }
        sb.append("/").append(databaseName);
        sb.append("?loginTimeout=").append(loginTimeout);
        sb.append("&socketTimeout=").append(socketTimeout);
        sb.append("&prepareThreshold=").append(prepareThreshold);
        sb.append("&unknownLength=").append(unknownLength);
        sb.append("&loglevel=").append(logLevel);
        if (protocolVersion != 0) {
            sb.append("&protocolVersion=").append(protocolVersion);
        }
        if (ssl) {
            sb.append("&ssl=true");
            if (sslfactory != null) {
                sb.append("&sslfactory=").append(sslfactory);
            }
        }
        sb.append("&tcpkeepalive=").append(tcpKeepAlive);
        if (compatible != null) {
            sb.append("&compatible="+compatible);
        }
        if (applicationName != null) {
            sb.append("&ApplicationName=");
            sb.append(applicationName);
        }

        return sb.toString();
    }

那么我的问题是。 好吧...如果 postgres 数据源不希望通过 url 而是通过各种不同的设置器进行配置,也许我可以通过添加到 application.properties 文件字段来摆脱困境,例如:

#spring.datasource.databaseName=dummydb

不,事实证明这似乎根本没有用。

经过一番调试,我成功找到了这个 Spring Boot 自动配置类:

org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration

上面的类非常有趣,因为它位于原子 JTA 事务子系统的配置路径中。 IT 将设置数据源:

org.postgresql.xa.PGXADataSource

但唯一的问题是这个自动配置器只关心 application.properties 文件中的三个属性。 请参阅下面的代码片段:

private void bindXaProperties(XADataSource target, DataSourceProperties properties) {
        MutablePropertyValues values = new MutablePropertyValues();
        values.add("user", this.properties.determineUsername());
        values.add("password", this.properties.determinePassword());
        values.add("url", this.properties.determineUrl());
        values.addPropertyValues(properties.getXa().getProperties());
        new RelaxedDataBinder(target).withAlias("user", "username").bind(values);
    }

如你所见,我似乎被“敬酒”了。 自动配置器不知道任何其他可能相关的数据源属性。 至少可以说我对此感到惊讶。 我期待某种类不会有任何东西,例如硬编码的属性子集,例如用户名和密码。 我期待某种代码会简单地循环所有 applicaton.properties 并寻找其键以以下开头的任何属性:

spring.datasource.whatever

并在数据源类上调用 datasource.setWhatever 。

似乎并非如此。

所以我确信我一定搞砸了一些事情。 我不敢相信,如果不强制开发人员创建自己的数据源 bean,springboot 将无法配置 postgres 数据库。 Postgress 简直太主流了……

所以我想知道是否有人可以帮助我弄清楚如何正确配置 application.properties 文件以确保我确实可以使用 springboot 连接到 postgres。

同时,我将看看是否可以通过以编程方式创建一个类来解决这个问题:

@AutoConfigureBefore(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(DataSourceProperties.class)
@ConditionalOnClass({ DataSource.class, TransactionManager.class,
        EmbeddedDatabaseType.class })
@ConditionalOnBean(XADataSourceWrapper.class)
@ConditionalOnMissingBean(DataSource.class)
public class XADataSourceAutoConfiguration implements BeanClassLoaderAware {

但就我而言,类将知道如何以编程方式构建具有所有连接所需属性的 postgres 数据源。

非常感谢您的帮助。

postgresql spring-boot configuration
1个回答
0
投票

问题是你没有在pgAdmin中正确创建数据库,在数据库选项中创建,而不是作为新服务器。

在此输入图片描述

© www.soinside.com 2019 - 2024. All rights reserved.