加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

java – 从Spring Boot连接到Heroku Postgres

发布时间:2020-12-15 01:41:55 所属栏目:大数据 来源:网络整理
导读:我正在寻找使用JPA / Hibernate在Spring Boot应用程序中连接到Heroku Postgres的最简单,最干净的方法. 我没有在Heroku或Spring Boot文档中看到这个组合的完整示例,所以我想在Stack Overflow上记录这个. 我想尝试这样的事情: @Configuration public class Da

我正在寻找使用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应该是首选,但现在我不再那么肯定了.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读