我正在寻找连接到Heroku Postgres的最简单、最清洁的方法,在使用JPA/Hibernate的Spring Boot应用程序中。
无论是在Heroku还是Spring Boot文档中,都没有这种组合的好的完整示例,因此我想在Stack Overflow上记录这个过程。
我正在尝试使用类似于以下内容:
@Configuration
public class DataSourceConfig {
Logger log = LoggerFactory.getLogger(getClass());
@Bean
@Profile("postgres")
public DataSource postgresDataSource() {
String databaseUrl = System.getenv("DATABASE_URL")
log.info("Initializing PostgreSQL database: {}", databaseUrl);
URI dbUri;
try {
dbUri = new URI(databaseUrl);
}
catch (URISyntaxException e) {
log.error(String.format("Invalid DATABASE_URL: %s", databaseUrl), e);
return null;
}
String username = dbUri.getUserInfo().split(":")[0];
String password = dbUri.getUserInfo().split(":")[1];
String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + ':'
+ dbUri.getPort() + dbUri.getPath();
// fully-qualified class name to distuinguish from javax.sql.DataSource
org.apache.tomcat.jdbc.pool.DataSource dataSource
= new org.apache.tomcat.jdbc.pool.DataSource();
dataSource.setUrl(dbUrl);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
我使用Profiles,它似乎很适合我想要的:在Heroku中,SPRING_PROFILES_ACTIVE
设置为postgres
,而在本地开发中,spring.profiles.active
设置为h2
以使用H2内存数据库(其配置在此处省略)。这种方法看起来很有效。在
application-postgres.properties
文件中(特定配置文件):spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.datasource.driverClassName=org.postgresql.Driver
DataSource
来自Tomcat似乎是很好的选择,因为默认依赖包含它,并且Spring Boot参考指南说:
出于性能和并发性考虑,我们更喜欢Tomcat池化数据源,因此如果可用,我们总是选择它。
(我还看到Spring Boot与Commons DBCP中的BasicDataSource一起使用。但对我而言,这似乎不是最清晰的选择,因为默认依赖项不包括Commons DBCP。而且总的来说,我在想Apache Commons在2015年是否真的是连接Postgres的推荐方式...此外Heroku文档针对此类场景提供了“Spring中的BasicDataSource”;我认为这指的是Commons DBCP,因为我在Spring本身中没有看到这样的类。)
依赖关系:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1205-jdbc42</version>
</dependency>
当前状态:出现“未加载JDBC驱动程序,因为driverClassName属性为空”错误:
eConfig$$EnhancerBySpringCGLIB$$463388c1 : Initializing PostgreSQL database: postgres:[...]
j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found
[...]
o.a.tomcat.jdbc.pool.PooledConnection : Not loading a JDBC driver as driverClassName property is null.
o.a.tomcat.jdbc.pool.PooledConnection : Not loading a JDBC driver as driverClassName property is null.
[...]
org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
在日志中我看到我的postgresDataSource
被正常调用,并且使用了PostgreSQLDialect(如果没有它,将会出现“当'hibernate.dialect'未设置时,无法访问DialectResolutionInfo”的错误信息)。
我的具体问题如下:
- 那么,如何使其工作?我正在设置
spring.datasource.driverClassName
,为什么会提示“未加载JDBC驱动程序,因为driverClassName属性为空”? - 使用Tomcat的
DataSource
是否可以,或者您推荐其他东西? - 必须像上面那样定义
postgresql
依赖关系并带有特定版本吗?(如果没有这个,我会收到“找不到合适的驱动程序”错误信息。) - 有没有更简单的方法来完成所有这些操作(同时遵循Java代码和/或属性;请勿使用XML)?
DATABASE_URL
有一件事情,就是Heroku会自动设置它,我应该从环境变量中读取和使用整个字符串,而不是将其部分内容存储在我的代码或配置中。在某些情况下它可能会更改。鉴于此,我不确定如何使用spring.datasource.url
等内容。(所有Heroku示例都会读取和拆分DATABASE_URL
环境变量。) - Jonik