我遇到的问题是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 数据源。
非常感谢您的帮助。
问题是你没有在pgAdmin中正确创建数据库,在数据库选项中创建,而不是作为新服务器。