spring bootで組み込みh2dbを利用する方法

### 1. はじめに

諸事情によりspring bootのWebアプリを作ることになりました。その際、組み込みh2dbを利用することなったので、その際、困ったことや調べたことをまとめました。
ちなみにspring bootのバージョンは１系の`1.5.17`です。

### 2. pom.xmlに依存関係を追加

`pom.xml`の依存関係に`spring-boot-starter-jdbc`と`h2`を追加します。
[Spring Initializr](https://start.spring.io/)でプロジェクトを作成する場合は以下の２つを追加すれば同じになります。

* H2
* JDBC

```xml:追加する依存関係
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
	<groupId>com.h2database</groupId>
	<artifactId>h2</artifactId>
	<scope>runtime</scope>
</dependency>
```

### 3. application.properties(.yml)に設定を追加

application.propertiesもしくはapplication.ymlに以下の設定を追加します。
設定内容は以下の３つです。

* datasourceの設定
* コネクションプールの設定（必要なら）
* h2の便利ツールの設定（必要なら）

```properties:src/main/resources/application.propertie
# datasource
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:./h2db/sampledb
spring.datasource.username=username
spring.datasource.password=password

# connection pool use tomcat
spring.datasource.tomcat.maxActive=10
spring.datasource.tomcat.maxIdle=10
spring.datasource.tomcat.minIdle=10
spring.datasource.tomcat.initialSize=10
spring.datasource.tomcat.defaultAutoCommit=false

# h2 for debug tool
# spring.h2.console.enabled=true
# spring.h2.console.path=/h2-console
# spring.h2.console.settings.web-allow-others=true
```

各設定の内容は[公式ガイドラインのappication.propertiesの説明](https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html)に書かれています。
以下、ポイントを説明します。

#### connection pool はプールとしてだけ利用する

`spring.datasource.tomcat.*= # Tomcat datasource specific settings`
とあるのでTomcatのdatasourceの定義と同様に`driverClass,url,username,password`も定義して、`spring.datasource.url`等を削除しました。
これはダメみたいです。あくまでプールとしてだけ定義するのが正しいみたいです。

組み込みDB、つまり同一JVMプロセスなのにプールが必要？と思われる方もいると思いますが、著者も同様です汗。一般的なWebアプリなら必要だよね、ということで設定しています。性能測定はしていないの効果は不明です。

```properties:誤り
# datasource
# nothing see connection pool

# connection pool use tomcat
spring.datasource.tomcat.driver-class-name=org.h2.Driver
spring.datasource.tomcat.url=jdbc:h2:./h2db/sampledb
spring.datasource.tomcat.username=username
spring.datasource.tomcat.password=password
spring.datasource.tomcat.maxActive=10
spring.datasource.tomcat.maxIdle=10
spring.datasource.tomcat.minIdle=10
spring.datasource.tomcat.initialSize=10
spring.datasource.tomcat.defaultAutoCommit=false
```

#### h2の便利機能はデバッグとして利用する

組み込みDBでもh2のWeb管理機能を利用することができます。
組み込みDBはアプリと同じJVMプロセスで動作し、専用DBのためネットワーク接続できないためデバッグするのはメンドウでした。
Web管理機能を使うと現在のDBのデータを参照したり、変更できるようになります。

```properties
# h2 for debug tool
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.h2.console.settings.web-allow-others=true
```

デバッグ機能なのでapplication.propetiesに有効な状態で設定するのではなく、システムプロパティで有効にするのがいいでしょう。
これなら設定ファイルの修正を忘れても、デバッグ機能は無効のままで安心です。

`java -jar your-app.jar -Dspring.h2.console.enabled=true -Dspring.h2.console.path=/h2-console -Dspring.h2.console.settings.web-allow-others=true`

ちなみに`spring.h2.console.settings.web-allow-others`はリモート（別PC）からのアクセスを許可するかどうかです。デフォルトの`false`ではローカルから、つまりアプリを実行しているPCからしかアクセスできません。

### 4. DBやテーブルの準備

h2dbはインメモリのDBですが、組み込みDBではデータは永続化することができます。
ということは、起動する毎に毎回初期化されてしまうと困ります。

* h2dbは接続文字列で指定したdbが存在しない場合は自動で作成する
  * 存在する場合は新規作成（初期化）しない
* `CREATE TABLE IF NOT EXISTS`で初期化SQLを定義する
  * テーブルが存在する場合は再作成されない
* `jdbc:h2:./h2db/sampledb`は実行時のカレントディレクトリから相対で見たパス（`./h2db/sampledb`）にDBファイルを格納する意味である
  * 相対パス指定は`./`が重要

### 5. jdbcTemplate、datasource、トランザクション制御は自動で設定される

springframeworkを素で利用すると、DBアクセスで必要ないろいろな設定（Bean定義やAOP等）が必要ですが、spring bootの場合は自動で設定されます。

* datasourceのBeanが自動で設定される
* `JdbcTemplate`,`NamedParameterJdbcTemplate`のBeanが自動で設定される
  * すぐに`@Autowired`等でインジェクションができる
* `@Transactional`によるトランザクション制御が有効

### 6. さいごに

今回はpring bootのWebアプリで、組み込みh2dbを利用する方法について、困ったことや調べたことをまとめました。
実際にやってみて、予想以上に設定が少なかったので驚きました。そう意味ではspring bootはお手軽ですね。