H2データベース — プロトタイピング

著者
Damian
Terlecki
1分間の読書
データベース

データ層は、通常、アプリケーションアーキテクチャの中核をなす要素です。開発中、サンプルやテストケースを作成する際に、何か軽量なものが必要になることがあるかもしれません。場合によっては、データベースに求められる要件が、素早くセットアップでき、あまり手間や考えをかけずに実行できることだけ、ということもあります。多くの場合、データにアクセスするためのコンソールアプリケーションさえ必要ありません。これは、自動テストや統合テストを実行する際によくあるケースです。しかし、データモデルのプロトタイピング(JPAデータベースの初期化)や、データベースのカラムに基づいたテストを作成する際には、私は中身がどうなっているのかをぜひ確認したいと思っています。

当初はMySQLやOracle DBのようなスタンドアロンのデータベースを使用していました。新しい環境ごとにそれらをセットアップしたり、他の誰かに頼んだりするのは、あまり快適ではありませんでした。その後、Dockerについて耳にしてすぐにそちらに切り替えました。ある時点までは、まさに天の恵みのようでした。しかし、後になって、小規模な(まだ本番準備ができていない)プロジェクトやデモサンプルを作成する際には、それほど多くのオーバーヘッドは必要ないことに気づきました。その時点から、HSQLDB、Apache Derby、SQLite、そしてH2 Databaseといった、さまざまなインメモリデータベースを使用してきました。

ごく最近になって、H2 Databaseがプロトタイピングとテストに必要なものをすべて備えていることに気づきました。Spring Bootと一緒に、pomファイルに依存関係を追加するだけで、ほぼ瞬時にセットアップできます。

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.194</version>
</dependency>

必要なものに応じてスコープを選択します。ライブラリから追加のツールを使用したい場合はcompile。アプリケーションの通常の使用(プロトタイピング)にはruntime。そして、統合テストを実行するためにはtest。これによって、とても手軽な感覚を得られます。Spring Bootが(JPAスターターで)面倒を見てくれるので、少なくともこの時点では、データベースの起動や設定について考える必要がありません。

コンソールとインメモリモード

H2コンソールログイン

さらに、H2にはWebサーバーコンソールが付属しています。Spring Boot(webおよびJPAスターター)を使用している場合、application.propertiesspring.h2.console.enabled=trueを追加することで有効にできます。Webコンソールはデフォルトのポートでh2-consoleパス(例: http://localhost:8080/h2-console)で起動します。エンティティクラスが準備されていれば、デフォルトのメモリDBインスタンスjdbc:h2:mem:testdbにテーブルが自動的に初期化されているのがわかるでしょう。

H2コンソール

Spring Bootを使用していなくても心配いりません。サーバーの起動はorg.h2.tools.Server.main()を実行するのと同じくらい簡単です。サーブレットコンテキストではorg.h2.server.web.DbStarterも役立つかもしれません。詳細な説明については、ドキュメントを参照してください。他のフレームワーク/言語(.NET)でデータベースを使用する方法についての情報を含む高度なセクションもあります。標準のJavaでWebサーバーの起動とともにデータベースへの手動接続を行うには、次のコードを使用します。

Connection connection = DriverManager.getConnection("jdbc:h2:mem:testdb", "sa", "");
Statement statement = connection.createStatement();
if(statement.execute("Select * from dual")) {
    System.out.println("Successfully connected to the jdbc:h2:mem:testdb");
}
Server.startWebServer(connection);

これにより、Webブラウザでコンソールが起動し、ランダムなポートで開かれるはずです。

サーバーモード

次に検討すべき便利なケースは、アプリケーションの外部、つまり異なるプロセス/ホストからデータベースに接続することです。データベースはインメモリで実行されているため、これは通常少し難しいです。デフォルトでは、DBには同じ仮想マシンとクラスローダー内からしかアクセスできません。しかし、H2のツールのおかげでTCPサーバーを使用して公開することも可能です。Springでサーバーを作成、起動、停止する役割を担うBeanの例は、次のように定義できます。

@Bean(initMethod = "start", destroyMethod = "stop")
public Server inMemoryH2DatabaseServer() throws SQLException {
    return Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", "9090");
}

これで、9090ポートで、JDBCドライバ(org.h2.Driver)を使い、jdbc:h2:tcp://localhost:9090/mem:testdbパスでデータベースにアクセスできるようになります。これにより、例えばJMeterのような別のアプリケーションからデータベースに接続して、データを確認したり、負荷テストを実行したりすることが可能になります。org.h2.tools.Serverクラスを使用するには、H2の依存関係をcompile(デフォルト)スコープで追加する必要があります。これは、いわゆるサーバーモードです。

組み込みモード

最後に、H2を組み込みモードで実行するように設定することも可能です。この方法では、データはファイルに保持され、アプリケーションの実行をまたいで永続化されます。Spring Bootでの設定は簡単です。application.propertiesでデータベースファイルのパスを定義します。

spring.datasource.url=jdbc:h2:./testdb
spring.jpa.hibernate.ddl-auto=update

デフォルトのcreate-drop値を上書きするために、spring.jpa.hibernate.ddl-auto=updateを使用する必要があります。これらのモードを組み合わせて、一つを「本番用」に、もう一つをテスト実行用に使用することもできます。これは、test/resourcesディレクトリに別のpropertiesファイルを作成するのと同じくらい簡単です。

ただし、どんなアプローチも良く聞こえるかもしれませんが、それには常にいくつかの利点と欠点が伴うことに注意してください。だからこそ、どのツールを選ぶか、そしてその見返りとして何を犠牲にするか(ユースケースによっては何もないかもしれませんが)を決めるのは、常に個人の判断に委ねられています。では、また!