java – 从Spring Boot连接到Heroku Postgres

前端之家收集整理的这篇文章主要介绍了java – 从Spring Boot连接到Heroku Postgres前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我正在寻找使用JPA / Hibernate在Spring Boot应用程序中连接到Heroku Postgres的最简单,最干净的方法.

我没有在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(profile-specific properties)中:

spring.jpa.database-platform=org.hibernate.dialect.PostgresqlDialect
spring.datasource.driverClassName=org.postgresql.Driver

Tomcat的DataSource似乎是一个不错的选择,因为默认的依赖包含它,因为Spring Boot reference guide says

We prefer the Tomcat pooling DataSource for its performance and
concurrency,so if that is available we always choose it.

(我也从Commons DBCP being used with Spring Boot看到BasicDataSource.但对我来说这似乎不是最干净的选择,因为默认依赖项不包括Commons DBCP.而且一般来说我想知道Apache Commons在2015年是否真的可以连接到Postgres的推荐方法…另外Heroku documentation为这种场景提供了“Spring中的BasicDataSource”;我认为这是指Commons DBCP,因为我在Spring本身没有看到这样的类.)

依赖关系:

当前状态:失败并显示“未加载JDBC驱动程序,因为driverClassName属性为null”:

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的使用是否正常,或者你会推荐别的吗?
>是否必须使用specific version定义上述postgresql依赖项? (没有这个,我得到“找不到合适的驱动程序”错误.)
>是否有更简单的方法来完成所有这些(同时坚持使用Java代码和/或属性;请不要使用XML)?

最佳答案
为了使数据库连接正常工作(以稳定的方式),我在问题中描述的设置中缺少两件事:

> As jny pointed out,我需要明确设置JDBC驱动程序:

> dataSource.setDriverClassName(“org.postgresql.Driver”);
>(原因是我正在定义一个自定义数据源,覆盖Spring的默认值,导致我的spring.datasource.driverClassName属性没有效果.据我所知,由于dynamic nature of Heroku’s DATABASE_URL,我需要自定义数据源来实现它工作.)

>此后连接工作,但不稳定;我开始得到org.postgresql.util.PsqlException:此连接已关闭.应用程序运行一段时间后.有点令人惊讶的solution(基于this answer)是在Tomcat DataSource上启用某些测试,例如testOnBorrow

> dataSource.setTestOnBorrow(true);
dataSource.setTestWhileIdle(真);
dataSource.setTestOnReturn(真);
dataSource.setValidationQuery(“SELECT 1”);

那么,我的DataSourceConfig的固定版本:

@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: {}",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();

        org.apache.tomcat.jdbc.pool.DataSource dataSource 
            = new org.apache.tomcat.jdbc.pool.DataSource();
        dataSource.setDriverClassName("org.postgresql.Driver");
        dataSource.setUrl(dbUrl);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setTestOnBorrow(true);
        dataSource.setTestWhileIdle(true);
        dataSource.setTestOnReturn(true);
        dataSource.setValidationQuery("SELECT 1");
        return dataSource;
    }

}

仅在application-postgres.properties中使用:

spring.jpa.database-platform=org.hibernate.dialect.PostgresqlDialect

现在,我遇到的两个问题可能都是特定于DataSource from Tomcat(org.apache.tomcat.jdbc.pool). Apparently BasicDataSource(Commons DBCP)具有更明智的默认值.但正如问题中提到的,我宁愿使用Spring Boot默认配置的东西,特别是参考指南中的strongly endorsed.

我愿意接受竞争/更简单/更好的解决方案,所以请随意发帖,特别是如果你能在问题的最后解决疑惑2-4!

而是使用JDBC_DATABASE_ *变量

更新:请注意,使用JDBC_DATABASE_ *比上面简单得多,如pointed out in this answer.很长一段时间我的印象是DATABASE_URL应该是首选,但现在我不再那么肯定了.

猜你在找的Spring相关文章