jjzjj

java - 从Spring Boot连接到Heroku Postgres

coder 2024-03-10 原文

我正在寻找使用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.activeh2以使用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本身看不到此类。)

依存关系:
<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>

当前状态:失败,因为“由于driverClassName属性为null,未加载JDBC驱动程序”:
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的访问不能为null”而失败)。

我的具体问题
  • 那么,如何使它工作?我正在设置spring.datasource.driverClassName,那么为什么“不将JDBC驱动程序作为driverClassName属性加载为null”?
  • 可以很好地使用Tomcat的DataSource还是您会推荐其他方法?
  • 是否必须使用specific version像上面那样定义postgresql依赖项? (如果没有这个,我将收到“找不到合适的驱动程序”错误。)
  • 是否有更简单的方法来完成所有这些工作(同时坚持使用Java代码和/或属性;请不要使用XML)?
  • 最佳答案

    使用Heroku和Postgres最简单的Spring Boot 2.x清洁方式

    我阅读了所有答案,但没有找到Jonik在寻找什么:

    I'm looking for the simplest, cleanest way of connecting to Heroku Postgres in a Spring Boot app using JPA/Hibernate



    大多数人希望与Spring Boot&Heroku一起使用的开发过程包括用于测试和快速开发周期的本地H2内存数据库,以及用于在Heroku上进行登台和生产的Heroku Postgres database
  • 首先是-您不需要为此使用Spring配置文件!
  • 第二:您无需编写/更改任何代码!

  • 让我们逐步了解一下我们要做的事情。我有一个示例项目,该示例项目为Postgres提供了完整的Heroku部署和配置-仅出于完整性考虑,如果您想自己对其进行测试:github.com/jonashackt/spring-boot-vuejs

    pom.xml

    我们需要以下依赖:
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
    
        <!-- In-Memory database used for local development & testing -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
    
        <!-- Switch back from Spring Boot 2.x standard HikariCP to Tomcat JDBC,
        configured later in Heroku (see https://stackoverflow.com/a/49970142/4964553) -->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jdbc</artifactId>
        </dependency>
    
        <!-- PostgreSQL used in Staging and Production environment, e.g. on Heroku -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.2.2</version>
        </dependency>
    

    这里一件棘手的事情是tomcat-jdbc的用法,但我们将在一秒钟内介绍它。

    在Heroku上配置环境变量

    在Heroku中,环境变量被命名为Config Vars您没听错,我们要做的就是配置环境变量! 我们只需要正确的。因此,转到https://data.heroku.com/(我假设已经为您的Heroku应用配置了Postgres数据库,这是默认行为)。

    现在,单击您的应用程序对应的Datastore,然后切换到Settings选项卡。然后单击View Credentials...,其外观应类似于以下内容:



    现在,打开一个新的浏览器选项卡,并转到您的Heroku应用程序的Settings选项卡。单击Reveal Config Vars并创建以下环境变量:
  • SPRING_DATASOURCE_URL = jdbc :postgres ql :// YourPostgresHerokuHostNameHere :5432/ YourPostgresHerokuDatabaseName此处(请注意)
  • jdbc: = YourPostgresHerokuUserName此处
  • ql = YourPostgresHerokuPasswordHere
  • postgres = SPRING_DATASOURCE_USERNAME(这并不总是需要since Spring Boot can deduce it for most databases from the url,只是为了完整起见)
  • SPRING_DATASOURCE_PASSWORD = SPRING_DATASOURCE_DRIVER-CLASS-NAME
  • org.postgresql.Driver = SPRING_JPA_DATABASE-PLATFORM
  • org.hibernate.dialect.PostgreSQLDialect = SPRING_DATASOURCE_TYPE(这将根据您的JPA实体自动创建表,这非常好-因为您不需要使用org.apache.tomcat.jdbc.pool.DataSource SQL语句或DDL文件就可以了)

  • 在Heroku中,应如下所示:



    现在这就是您要做的! 每次更改配置变量时,都会重新启动Heroku应用程序-因此,您的应用程序现在应该在本地运行H2,并且在部署到Heroku上后应该可以与PostgreSQL连接。

    就像您在问:为什么我们配置Tomcat JDBC而不是Hikari

    您可能会注意到,我们在pom.xml中添加了SPRING_JPA_HIBERNATE_DDL-AUTO依赖项,并将update配置为Environment变量。只有a slight hint in the docs about this的话

    You can bypass that algorithm completely and specify the connection pool to use by setting the spring.datasource.type property. This is especially important if you run your application in a Tomcat container, ...



    我切换回Tomcat池化DataSource而不是使用Spring Boot 2.x标准HikariCP的原因有很多。正如我already explained here一样,如果您未指定CREATE,Spring将尝试自动连接嵌入式内存H2数据库,而不是我们的PostgreSQL数据库。 Hikari的问题在于,它仅支持tomcat-jdbc

    其次,如果我尝试使用Hikari所示的Heroku配置(因此省略SPRING_DATASOURCE_TYPE=org.apache.tomcat.jdbc.pool.DataSource并将spring.datasource.url更改为spring.datasource.jdbc-url),则会遇到以下异常:
    Caused by: java.lang.RuntimeException: Driver org.postgresql.Driver claims to not accept jdbcUrl, jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    

    因此,我没有让Spring Boot 2.x与HikariCP一起在Heroku和Postgres上运行,而是与Tomcat JDBC一起工作-而且我也不想阻止我的包含先前描述的本地H2数据库的开发过程。记住:我们在寻找使用JPA/Hibernate在Spring Boot应用程序中连接到Heroku Postgres的最简单,最干净的方法!

    关于java - 从Spring Boot连接到Heroku Postgres,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33633243/

    有关java - 从Spring Boot连接到Heroku Postgres的更多相关文章

    1. ruby - 续集在添加关联时访问many_to_many连接表 - 2

      我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

    2. java - 等价于 Java 中的 Ruby Hash - 2

      我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

    3. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

      我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

    4. java - 从 JRuby 调用 Java 类的问题 - 2

      我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

    5. java - 我的模型类或其他类中应该有逻辑吗 - 2

      我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

    6. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

      什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

    7. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

      这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

    8. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

      HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

    9. 【Java入门】使用Java实现文件夹的遍历 - 2

      遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

    10. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

      我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

    随机推荐