source

Spring Boot에서 Heroku Postgres에 연결

ittop 2023. 6. 26. 23:11
반응형

Spring Boot에서 Heroku Postgres에 연결

JPA/하이버네이트를 사용하여 스프링 부트 앱에서 헤로쿠 포스트그레스에 연결하는 가장 간단하고 깨끗한 방법을 찾고 있습니다.

Heroku 또는 Spring Boot 설명서에서 이 조합에 대한 좋은 완전한 예제가 보이지 않으므로 스택 오버플로에 대해 문서화하려고 합니다.

저는 다음과 같은 것을 시도하고 있습니다.

@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;
    }

}

저는 제가 원하는 것과 잘 맞는 프로파일을 사용하고 있습니다: 헤로쿠에서.SPRING_PROFILES_ACTIVE으로 설정됨postgres을 하는 .spring.profiles.active이라h2H2 인 메모리 데이터베이스를 사용합니다(여기에서는 구성이 생략됨).이 방법은 잘 작동하는 것 같습니다.

application-postgres.properties(프로파일별 속성):

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

DataSourceTomcat은 기본 종속성에 포함되어 있고 Spring Boot 참조 가이드에 다음과 같이 나와 있기 때문에 좋은 옵션처럼 보였습니다.

성능과 동시성을 위해 Tomcat 풀링 데이터 소스를 선호하기 때문에 가능하다면 항상 선택합니다.

있어요.BasicDataSource스프링 부트와 함께 사용되는 Commons DBCP에서.그러나 기본 종속성에 Commons DBCP가 포함되어 있지 않기 때문에 이것이 가장 깨끗한 선택으로 보이지 않습니다.그리고 일반적으로 2015년에 Apache Commons가 Postgres에 연결하는 권장 방법이 될 수 있는지 궁금합니다.또한 헤로쿠 문서는 "BasicDataSource이러한 시나리오에 대해 "봄에"; 나는 봄 자체에서 그러한 클래스를 보지 않기 때문에 이것이 Commons DBCP를 가리키는 것이라고 추측합니다.)

종속성:

<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그냥 좋아요, 그리고 그 포스트그리는.SQL Dialect가 사용 중입니다(이 기능이 없으면 "방언 해상도 액세스"가 실패했습니다).'hibernate.dialect'가 설정되지 않은 경우 정보는 null일 수 없습니다.").

나의 구체적인 질문

  1. 어떻게 하면 잘 될 수 있을까요?설정 중입니다.spring.datasource.driverClassName그렇다면 "driverClassName 속성이 null이므로 JDBC 드라이버를 로드하지 않음"은 이유는 무엇입니까?
  2. Tomcat을 입니까?DataSource좋아요, 아니면 다른 것을 추천하시겠습니까?
  3. 정의할 필요가 있습니까?postgresql와 같은 특정 버전과의 종속성?(이것이 없으면 "적절한 드라이버를 찾을 수 없습니다" 오류가 발생했습니다.)
  4. (자바 코드 및/또는 속성을 고수하면서) 이 모든 것을 할 수 있는 더 간단한 방법이 있습니까? XML은 필요 없습니다.

Heroku & Postgres와 함께하는 가장 간단한 스프링 부트 2.x 청소 방법

저는 모든 답을 읽었지만 Jonik이 무엇을 찾고 있는지 찾지 못했습니다.

JPA/Hibernate를 사용하여 봄 부팅 앱에서 Heroku Postgres에 연결하는 가장 간단하고 깨끗한 방법을 찾고 있습니다.

대부분의 사람들이 Spring Boot & Heroku와 함께 사용하기를 원하는 개발 프로세스에는 테스트 및 빠른 개발 주기를 위한 로컬 H2 인 메모리 데이터베이스와 Heroku에서 스테이징 및 프로덕션을 위한 Heroku Postgres 데이터베이스가 포함되어 있습니다.

  • 첫 번째는 스프링 프로필을 사용할 필요가 없다는 것입니다!
  • 두 번째: 코드를 작성/변경할 필요가 없습니다!

우리가 해야 할 일을 차근차근 살펴보도록 하겠습니다.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 고리다로전다니환합으음으로 합니다.Settingstab.그에 를 하세요.View Credentials...다음과 같이 유사하게 보여야 합니다.

heroku-datastore-credentials-postgres

새 의 Heroku 응용 프로그램으로 합니다.Settings탭도 있습니다.Reveal Config Vars다음 환경 변수를 생성합니다.

  • SPRING_DATASOURCE_URLjdbc:postgresql://YourPostgresHerokuHostName여기:5432/YourPostgresHerokuDatabaseName여기(앞에 주의)jdbc: 리고그고.qlpostgres!)
  • SPRING_DATASOURCE_USERNAME귀하의 사용자 이름Heroku 사용자 이름여기서
  • SPRING_DATASOURCE_PASSWORD당신의 Password Here Heroku입니다.
  • SPRING_DATASOURCE_DRIVER-CLASS-NAME=org.postgresql.Driver(Spring Boot은 URL에서 대부분의 데이터베이스에 대해 이를 추론할 수 있기 때문에 항상 필요한 것은 아닙니다.)
  • SPRING_JPA_DATABASE-PLATFORM=org.hibernate.dialect.PostgreSQLDialect
  • SPRING_DATASOURCE_TYPE=org.apache.tomcat.jdbc.pool.DataSource
  • SPRING_JPA_HIBERNATE_DDL-AUTO=update은 당신의으로 당신의 테이블을 것입니다, - 을 할가 없기 입니다. 정말 좋습니다. 왜냐하면 당신은 허들을 사용할 필요가 없기 때문입니다.CREATESQL 문 또는 DDL 파일)

Heroku에서 이것은 다음과 같습니다.

heroku-spring-boot-app-postgres-config

이제 당신이 해야 할 일은 그것뿐입니다!구성 변수를 변경할 때마다 Heroku 앱이 다시 시작되므로 이제 앱이 H2를 로컬로 실행하고 Postgre와 연결할 준비가 되어 있어야 합니다.Heroku에 배포할 경우 SQL.

만약 당신이 묻고 싶은 것.Hikari 대신 Tomcat JDBC를 구성하는 이유는 무엇입니까?

눈치채셨겠지만, 우리는 다음을 추가했습니다.tomcat-jdbc 및 pom.xml에 입니다.SPRING_DATASOURCE_TYPE=org.apache.tomcat.jdbc.pool.DataSource환경 변수로 사용할 수 있습니다. 말에 대한 문서에는 약간의 힌트가 있을 입니다.

이 알고리즘을 완전히 무시하고 spring.datasource.type 속성을 설정하여 사용할 연결 풀을 지정할 수 있습니다.Tomcat 컨테이너에서 응용 프로그램을 실행하는 경우 특히 중요합니다.

스프링 부트 2.x 표준 HikariCP를 사용하는 대신 Tomcat 풀링 데이터 소스로 다시 전환한 몇 가지 이유가 있습니다.여기서 이미 설명했듯이, 만약 당신이 명시하지 않는다면,spring.datasource.url은 우리의 Postgre im-memory H2 대신 하려고 할 입니다.SQL 1. 그고히카문오것한다입니다는지원만직리제는의리▁supports다▁sql▁it,것▁only만 지원한다는 것입니다.spring.datasource.jdbc-url.

둘째, 만약 내가 히카리에 대해 표시된 것처럼 헤로쿠 구성을 사용하려고 한다면 (그래서 생략).SPRING_DATASOURCE_TYPE그리고 변화.SPRING_DATASOURCE_URLSPRING_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

그래서 저는 HikariCP와 함께 Heroku & Postgres를 작업하는 Spring Boot 2.x가 아니라 Tomcat JDBC와 함께 작업했습니다. 그리고 저는 또한 앞에서 설명한 로컬 H2 데이터베이스를 포함하는 개발 프로세스를 중단하고 싶지 않습니다.기억:우리는 JPA/하이버네이트를 사용하여 봄 부팅 앱에서 Heroku Postgres에 연결하는 가장 간단하고 깨끗한 방법을 찾고 있었습니다!

가장 단순한 스프링 부트 / Heroku / 최대 절전 모드 구성

▁▁apart을외.DATABASE_URLHeroku는 Runtime에서 3개의 환경 변수를 생성합니다.다음과 같습니다.

JDBC_DATABASE_URL
JDBC_DATABASE_USERNAME
JDBC_DATABASE_PASSWORD

은 Spring Boot을 합니다.spring.datasource.* application.properties입니다. application.properties 파일입니다.

spring.datasource.url=${JDBC_DATABASE_URL}
spring.datasource.username=${JDBC_DATABASE_USERNAME}
spring.datasource.password=${JDBC_DATABASE_PASSWORD}
spring.jpa.show-sql=false
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update

최대 절전 모드/최대 절전 모드 종속성

에는 HibernateHibernate" ("Hibernate" ("Hibernate"))를 사용합니다.spring-boot-starter-jpaPostgre Postgre와 SQL을 사용하여 SQL에 했습니다.build.gradle:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile('org.postgresql:postgresql:9.4.1212')
}

데이터베이스 연결이 안정적으로 작동하도록 하기 위해 질문에서 설명한 설정에서 두 가지가 누락되었습니다.

  • jny가 지적했듯이 JDBC 드라이버를 명시적으로 설정해야 했습니다.
    • dataSource.setDriverClassName("org.postgresql.Driver");
    • 는 사용자 하고 Spring의 기본값을 하여 내 ("Spring"의 Spring"을 spring.datasource.driverClassName효력이 없는 속성.그리고 Heroku의 동적 특성으로 인해 이를 작동시키기 위해 맞춤형 데이터 소스가 필요한 것으로 알고 있습니다.)
  • 이 후 연결은 작동했지만 안정적이지 않았습니다. 저는 연결하기 시작했습니다.org.postgresql.util.PSQLException: This connection has been closed.앱이 잠시 실행된 후.다소 놀라운 솔루션( 답변을 기반으로 함)은 Tomcat DataSource와 같은 특정 테스트를 활성화하는 것이었습니다.
    • dataSource.setTestOnBorrow(true); dataSource.setTestWhileIdle(true); dataSource.setTestOnReturn(true); dataSource.setValidationQuery("SELECT 1");

그래서, 내 데이터 소스 구성의 고정 버전:

@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();

        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

이제, 제가 가진 두 가지 문제 모두 Tomcat의 데이터 소스에만 국한된 것일 수 있습니다.org.apache.tomcat.jdbc.poolBasic DataSource(Commons DBCP)는 보다 합리적인 기본값을 가지고 있습니다.그러나 질문에서 언급했듯이, 저는 특히 참조 가이드에서 강력하게 지지하는 것처럼 기본적으로 스프링 부트와 함께 제공되는 것을 사용했습니다.

저는 경쟁력 있는/더 간단한/더 나은 솔루션을 선호합니다. 특히 질문의 마지막 부분에서 2-4개의 의문점을 해결할 수 있다면 언제든지 게시하십시오.

용사를 합니다.JDBC_DATABASE_* 대신

를 사용합니다. : 를 사용합니다.JDBC_DATABASE_* 답변에서 지적한 바와 같이 위보다 훨씬 단순합니다.오랫동안 나는 그들이 그들을DATABASE_URL더 선호되어야 하지만, 요즘은 더 이상 확신할 수 없습니다.

JDBC_DATABASE_URL을 사용해 보십시오.spring.datasource.urlDATABASE_URL을 구문 분석하는 대신

DATABASE_URL을 구문 분석하는 것이 권장되지만 작동할 수 없는 경우 JDBC_DATABASE_URL은 정상입니다.

이것은 Heroku가 제공하는 샘플 Java Application에 대한 Postgres 문제에 대한 최고 답변입니다.

이 단계는 이를 실현하기 위해 수행한 것입니다(Windows 7).

1.) 운영 서버 application.properties 파일에 시스템 환경이 포함됩니다(이 파일이 커밋되었는지 확인).

spring.datasource.url=${JDBC_DATABASE_URL}
spring.datasource.username=${JDBC_DATABASE_USERNAME}
spring.datasource.password=${JDBC_DATABASE_PASSWORD}

2.) 이제 합니다.git update-index --assume-unchanged .\src\main\resources\application.properties

합니다.3.) application.properties를 변경합니다.은 raw 값을 할 수 .heroku run env

spring.datasource.url=jdbc://..
spring.datasource.username=XYZ
spring.datasource.password=ABC

이것은 제가 제 애플리케이션의 로컬 복사본을 작동시키기 위해 필요한 것입니다.더 좋은 방법을 찾은 사람이 있다면 공유해주세요!

@Configuration
@Component
public class HerokuConfigCloud {

private static final Logger logger = 
LoggerFactory.getLogger(HerokuConfigCloud .class);

@Bean()
//@Primary this annotation to be used if more than one DB Config was used.  In that case,
// using @Primary would give precedence to a the particular "primary" config class
@Profile("heroku")
public DataSource dataSource(
        @Value("${spring.datasource.driverClassName}") final String driverClass,
        @Value("${spring.datasource.url}") final String jdbcUrl,
        @Value("${spring.datasource.username}") final String username,
        @Value("${spring.datasource.password}") final String password
        ) throws URISyntaxException {


    return DataSourceBuilder
            .create()
            .username(username)
            .password(password)
            .url(url)
            .driverClassName(driverClass)
            .build();
    }
}

이것을 쉽게 하기 위해 도서관을 지었습니다: https://github.com/vic-cw/heroku-postgres-helper

빌드 스크립트와 응용프로그램 논리 모두에서 데이터베이스에 액세스해야 하는 경우 이 기능이 더욱 유용합니다.이유를 확인해 보십시오.

용도:

build.gradle:

// If using connection string in build script:
buildscript {
    repositories {
        maven { url 'https://jitpack.io' }
    }
    dependencies {
        classpath 'com.github.vic-cw:heroku-postgres-helper:0.1.0'
    }
}
import com.github.viccw.herokupostgreshelper.HerokuPostgresHelper;

// Use connection string in build script:
flyway {
    url = HerokuPostgresHelper.getDatabaseJdbcConnectionString()
    driver = 'org.postgresql.Driver'
}

// If using connection string inside application logic:
repositories {
    maven { url 'https://jitpack.io' }
}

dependencies {
    compile group: 'com.github.vic-cw', name: 'heroku-postgres-helper', version: '0.1.0'
}

Java 응용 프로그램 코드:

import com.github.viccw.herokupostgreshelper.HerokuPostgresHelper;

...

String databaseConnectionString = HerokuPostgresHelper.getDatabaseJdbcConnectionString();

언급URL : https://stackoverflow.com/questions/33633243/connecting-to-heroku-postgres-from-spring-boot

반응형