Java を使用して Heroku でリレーショナルデータベースに接続する
最終更新日 2024年05月09日(木)
Table of Contents
- JDBC_DATABASE_URL の使用
- Spring Boot アプリでの SPRING_DATASOURCE_URL の使用
- Spring Boot アプリでの JDBC_DATABASE_URL の使用
- Play Framework アプリでの DATABASE_URL の使用
- プレーン JDBC での DATABASE_URL の使用
- Spring の XML 設定での DATABASE_URL の使用
- Spring の Java 設定での DATABASE_URL の使用
- Hibernate での DATABASE_URL の使用
- PostgreSQL での SSL の使用
- リモートでデータベースに接続する
- データベース移行の実行
- Heroku Postgres Connection Pooling での使用
- サンプルプロジェクト
- より深い学習
Heroku 上のアプリケーションでは、Heroku によって提供される Postgres データベースを含む、さまざまなリレーショナルデータベースサービスを使用できます。
データベースはアドオンシステムを使用してプロビジョニングされます。一部のアプリケーションでは Heroku Postgres データベースがデフォルトでプロビジョニングされます。データベースがあるかどうかは、heroku info
を実行してアドオンのリストを表示することによって確認できます。
$ heroku info
=== sparkling-wine-2003
Web URL: http://sparkling-wine-2003.herokuapp.com/
Git Repo: git@heroku.com:sparkling-wine-2003.git
Repo size: 21M
Slug size: 916k
Stack: heroku-18
Data size: (empty)
Addons: Heroku Postgresql Essential 0
Owner: jesper@heroku.com
データベースが自動的にプロビジョニングされるかどうかは、buildpack によって異なります。データベースは、次のようにして手動でプロビジョニングできます。
$ heroku addons:create heroku-postgresql
アプリケーションにリレーショナルデータベースをプロビジョニングしました。アプリケーションは DATABASE_URL
環境設定からデータベース接続情報を読み取ります。これは次のような形式です。
[database type]://[username]:[password]@[host]:[port]/[database name]
次に例を示します。
postgres://foo:foo@heroku.com:5432/hellodb
アプリケーションに提供されている DATABASE_URL
は、次のように実行して確認できます。
$ heroku config
DATABASE_URL => postgres://foo:foo@heroku.com:5432/hellodb
環境によって値が変更される場合があるため、この値を静的ファイルにコピーすることはお勧めできません。代わりに、アプリケーションでは DATABASE_URL
環境変数 (または後述する JDBC_DATABASE_URL
変数) を読み取り、その情報に基づいてデータベース接続を設定するようにしてください。
JDBC_DATABASE_URL
の使用
Java、Scala、Clojure、Gradle 用の公式 Heroku buildpack では、dyno の起動時に JDBC_DATABASE_URL
環境変数の作成を試みます。この変数は動的であり、heroku config
を実行しても環境設定の一覧に表示されません。次のコマンドを実行すると表示できます。
$ heroku run echo \$JDBC_DATABASE_URL
変数には ?user=<user>&password=<password>
パラメータが含まれますが、可能であれば JDBC_DATABASE_USERNAME
および JDBC_DATABASE_PASSWORD
環境変数も設定されます。
データベース URL の確実なソースは引き続き DATABASE_URL
環境変数ですが、ほとんどの場合 JDBC_DATABASE_URL
を使用できます。
Java buildpack により、ClearDB MySQL、JawsDB MySQL、および JawsDB Maria の各アドオン用の JDBC_DATABASE_URL
も設定されます。
HEROKU_POSTGRESQL_<COLOR>
形式を使用するデータベースの場合、Java buildpack により HEROKU_POSTGRESQL_<COLOR>_JDBC_URL
、HEROKU_POSTGRESQL_<COLOR>_JDBC_USERNAME
、および HEROKU_POSTGRESQL_<COLOR>_JDBC_PASSWORD
の各環境設定が作成されます。
Spring Boot アプリでの SPRING_DATASOURCE_URL
の使用
Java および Gradle 用の公式 Heroku buildpack では、dyno の起動時に SPRING_DATASOURCE_URL
、SPRING_DATASOURCE_USERNAME
、および SPRING_DATASOURCE_PASSWORD
の各環境変数の作成を試みます。変数の値は、対応する JDBC
変数での値と同じになります。
アプリケーションで適切な JDBC ドライバーが依存関係として定義されている限り、これらの環境変数により、他の設定なしで Spring Boot アプリケーションからデータベースに接続できます。
事前定義された SPRING_DATASOURCE_*
環境変数を上書きする必要がある場合、heroku config:set
コマンドを使用して自分自身で設定することも、ダッシュボードで設定することもできます。あるいは、OS レベルの環境変数よりも優先される -Dspring.datasource.url
プロパティを Procfile
に追加できます。
Spring Boot アプリでの JDBC_DATABASE_URL
の使用
Spring Boot では、異なる環境で同じアプリケーションコードを扱えるよう、設定を外部化することができます。プロパティファイル、YAML ファイル、環境変数、およびコマンドライン引数を使用して設定を外部化できます。
次のように、application.yml
ファイルでデータベース URL を設定できます。
spring:
datasource:
url: ${JDBC_DATABASE_URL}
username: ${JDBC_DATABASE_USERNAME}
password: ${JDBC_DATABASE_PASSWORD}
詳細は、外部化された設定に関する Spring の公式ドキュメントを参照してください。
Play Framework アプリでの DATABASE_URL
の使用
Play Framework では、DATABASE_URL
環境変数が最初からサポートされています。conf/application.conf
に追加することによって、この値を使用するように組み込みの ORM フレームワークを設定できます。
db.default=${DATABASE_URL}
Play Framework で Slick を使用する場合、設定は次のようになります。
slick.dbs.default.driver="slick.driver.PostgresDriver$"
slick.dbs.default.db.dataSourceClass = "slick.jdbc.DatabaseUrlDataSource"
slick.dbs.default.db.properties.driver = "org.postgresql.Driver"
詳細は、Play Slick モジュールに関する Play のドキュメントを参照してください。
プレーン JDBC での DATABASE_URL
の使用
コードで JDBC 接続をインスタンス化するために、次のようなメソッドを使用できます。
private static Connection getConnection() throws URISyntaxException, SQLException {
String dbUrl = System.getenv("JDBC_DATABASE_URL");
return DriverManager.getConnection(dbUrl);
}
DATABASE_URL
を直接使用するときは、次のようになります。
private static Connection getConnection() throws URISyntaxException, SQLException {
URI dbUri = new URI(System.getenv("DATABASE_URL"));
String username = dbUri.getUserInfo().split(":")[0];
String password = dbUri.getUserInfo().split(":")[1];
String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + ':' + dbUri.getPort() + dbUri.getPath();
return DriverManager.getConnection(dbUrl, username, password);
}
注:
Heroku Postgres アドオン用の DATABASE_URL
は、次の規則に従います。
postgres://<username>:<password>@<host>:<port>/<dbname>
ただし、Postgres JDBC ドライバーは次の規則を使用します。
jdbc:postgresql://<host>:<port>/<dbname>?user=<username>&password=<password>
URL スキームの最後にある追加の ql
に注意してください。この違いのため、Postgres では、Java クラスまたは Spring XML 設定の postgresql
にスキーマをハードコーディングすることが必要な場合があります。
Spring の XML 設定での DATABASE_URL
の使用
Spring XML 設定のこのスニペットは、DATABASE_URL
から BasicDataSource
を設定し、その後 Hibernate や JPA などで使用できます。
<bean class="java.net.URI" id="dbUrl">
<constructor-arg value="#{systemEnvironment['DATABASE_URL']}"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url" value="#{ 'jdbc:postgresql://' + @dbUrl.getHost() + ':' + @dbUrl.getPort() + @dbUrl.getPath() }"/>
<property name="username" value="#{ @dbUrl.getUserInfo().split(':')[0] }"/>
<property name="password" value="#{ @dbUrl.getUserInfo().split(':')[1] }"/>
</bean>
Spring の Java 設定での DATABASE_URL
の使用
または、Spring で BasicDataSource
の設定に Java を使用できます。
@Configuration
public class MainConfig {
@Bean
public BasicDataSource dataSource() throws URISyntaxException {
String dbUrl = System.getenv("JDBC_DATABASE_URL");
String username = System.getenv("JDBC_DATABASE_USERNAME");
String password = System.getenv("JDBC_DATABASE_PASSWORD");
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setUrl(dbUrl);
basicDataSource.setUsername(username);
basicDataSource.setPassword(password);
return basicDataSource;
}
}
DATABASE_URL
を直接使用するときは、次のようになります。
@Configuration
public class MainConfig {
@Bean
public BasicDataSource dataSource() throws URISyntaxException {
URI dbUri = new URI(System.getenv("DATABASE_URL"));
String username = dbUri.getUserInfo().split(":")[0];
String password = dbUri.getUserInfo().split(":")[1];
String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + ':' + dbUri.getPort() + dbUri.getPath();
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setUrl(dbUrl);
basicDataSource.setUsername(username);
basicDataSource.setPassword(password);
return basicDataSource;
}
}
ここでも、サブプロトコルの違いに注意してください。DATABASE_URL
は postgres
を使用する一方、JDBC には値 postgresql
が必要です。
Hibernate での DATABASE_URL
の使用
他の何らかのフレームワークの外側で hibernate.cfg.xml
を使用して Hibernate を手動で設定している場合、サービスレジストリを構築するときに Java コードで JDBC URL を設定できます。次に例を示します。
Map<String,String> jdbcUrlSettings = new HashMap<>();
String jdbcDbUrl = System.getenv("JDBC_DATABASE_URL");
if (null != jdbcDbUrl) {
jdbcUrlSettings.put("hibernate.connection.url", System.getenv("JDBC_DATABASE_URL"));
}
registry = new StandardServiceRegistryBuilder().
configure("hibernate.cfg.xml").
applySettings(jdbcUrlSettings).
build();
これにより、hibernate.cfg.xml
で設定している URL が上書きされます。
PostgreSQL での SSL の使用
従来は、URL パラメータ sslmode=disable
を JDBC URL に追加することを提案していました。すべての新しい Heroku Postgres データベースで SSL の使用が必須になりました。2018 年 3 月から、すべての Heroku Postgres データベースで SSL の使用が義務化される予定です。データベースで SSL を無効化しないでください。無効化すると、アプリケーションが動作しなくなる可能性があります。
デフォルトで、Heroku は、プロパティ sslmode=require
をグローバルで設定することによって、PostgreSQL JDBC ドライバーに対して SSL を有効にしようとします。Heroku Postgres のすべてのデータベース接続で SSL の使用が必要です。デフォルトの sslmode
は、クラスパスに自動的に追加される小さなプロパティファイルで設定されます。heroku config:set SKIP_PGCONFIG_INSTALL=true
を実行することによって、このファイルが挿入されないようにします。
他のデータベースベンダーのドライバーは影響を受けません。
リモートでデータベースに接続する
Heroku Postgres データベースを使用している場合、メンテナンスやデバッグのためにリモートからデータベースに接続できます。ただしそうするには、SSL 接続を使用する必要があります。JDBC 接続 URL には、次の URL パラメータを含める必要があります。
sslmode=require
次に例を示します。
jdbc:postgresql://<host>:<port>/<dbname>?sslmode=require&user=<username>&password=<password>
sslmode=require
を追加しない場合、接続エラーが発生します。
Postgres JDBC ドライバーでの SSL サポートについての詳細は、公式の PostgreSQL ドキュメントを参照してください。その他の SQL データベースについては、SSL サポートの設定方法について、ベンダー固有の JDBC ドキュメントを参照してください。
環境設定を直接編集するのではなく、コードにこのパラメータを追加することが重要です。フェイルオーバーなどの自動化されたさまざまなイベントにより、環境設定が変更されることがあり、そこでの編集は失われます。
mTLS 経由で Private または Shield データベースに接続するとき、JDBC 接続 URL に追加パラメータが必要です。詳細は、mTLS 経由の接続に関するドキュメントを参照してください。
データベース移行の実行
ほとんどのデータベースでは、いずれかの時点でスキーマを変更することが必要になります。Liquibase や Flyway などの移行ツールは、これらの変更のバージョン履歴を管理します。Heroku でこれらを実行する方法については、「Java アプリ用のデータベース移行の実行」の記事を参照してください。
Heroku Postgres Connection Pooling での使用
Heroku Postgres Connection Pooling で JDBC を使用するとき、JDBC_DATABASE_URL
は、DATABASE_CONNECTION_POOL_URL
環境設定によって定義された値に設定されます。
サンプルプロジェクト
Heroku でデータベース接続を設定するさまざまな方法を示すサンプルプロジェクトは、次の場所にあります。 https://github.com/heroku/devcenter-java-database
試してみるには、まず Git リポジトリを複製します。
git clone git://github.com/heroku/devcenter-java-database.git
devcenter-java-database
ディレクトリで、プロジェクトの Maven ビルドを実行します。
mvn package
ローカルの Postgres データベースがあり、ローカルでテストしたい場合は、まず DATABASE_URL
環境変数を (正しい値を使用して) 設定します。
- Linux/Mac の場合:
export DATABASE_URL=postgres://foo:foo@localhost/hellodb
- Windows の場合:
set DATABASE_URL=postgres://foo:foo@localhost/hellodb
サンプルアプリケーションをローカルで実行するには、生成された開始スクリプトを実行します。
- Linux/Mac の場合:
sh devcenter-java-database-plain-jdbc/target/bin/main
sh devcenter-java-database-spring-xml/target/bin/main
sh devcenter-java-database-spring-java/target/bin/main
- Windows の場合:
devcenter-java-database-plain-jdbc/target/bin/main.bat
devcenter-java-database-spring-xml/target/bin/main.bat
devcenter-java-database-spring-java/target/bin/main.bat
コマンドごとに、問題がなかったことを示す次のようなメッセージが表示されます。
Read from DB: 2011-11-23 11:37:03.886016
Heroku で実行するには、まず新しいアプリケーションを作成します。
$ heroku create
Creating stark-sword-398... done, stack is heroku-18
http://stark-sword-398.herokuapp.com/ | git@heroku.com:stark-sword-398.git
Git remote heroku added
次に、アプリケーションを Heroku にデプロイします。
$ git push heroku master
Counting objects: 70, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (21/21), done.
Writing objects: 100% (70/70), 8.71 KiB, done.
Total 70 (delta 14), reused 70 (delta 14)
-----> Heroku receiving push
-----> Java app detected
-----> Installing Maven 3.0.3..... done
-----> executing /app/tmp/repo.git/.cache/.maven/bin/mvn -B -Duser.home=/tmp/build_2y7ju7daa9t04 -Dmaven.repo.local=/app/tmp/repo.git/.cache/.m2/repository -DskipTests=true clean install
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] devcenter-java-database-plain-jdbc
[INFO] devcenter-java-database-spring-xml
[INFO] devcenter-java-database-spring-java
[INFO] devcenter-java-database
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building devcenter-java-database-plain-jdbc 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
Downloading: http://s3pository.heroku.com/jvm/postgresql/postgresql/9.0-801.jdbc4/postgresql-9.0-801.jdbc4.pom
...
その後、任意のサンプルを Heroku で実行します。
$ heroku run "sh devcenter-java-database-plain-jdbc/target/bin/main"
Running sh devcenter-java-database-plain-jdbc/target/bin/main attached to terminal... up, run.1
Read from DB: 2011-11-29 20:36:25.001468