SpringBootのJUnitによるテスト設定で、「spring.sql.init.mode=always
って設定する必要あるの?、@Transactional
があれば不要じゃない?」と思っていたのが完全に間違いであったので、その詳細を解説する。
結論としては、(私のプロジェクト内では)
-
spring.sql.init.mode=always
は不要 -
spring.sql.init.mode
と@Transactional
は無関係
前提条件
環境
IDE | 言語 | APPフレームワーク | テストフレームワーク | SQL制御 | SQL |
---|---|---|---|---|---|
IntelliJ IDEA 2024.1.4 | java 21.0.4 | Spring Boot 3.3.3 | JUnit 5 | MyBatis 3.0.3 | MySQL 8.0.39 |
インメモリDBと組み込みDB
後のテスト用データベース設定の話をする前に、この2つの違いを把握しておく必要がある。
また、この記事内では以降データベースが下記の各状態になっていることをそれぞれインメモリモード、組み込みモードと呼ぶこととする。
インメモリデータベース
データをメモリ上に保持するデータベースであり、メモリから直接アクセスするため、通常のディスクベースのデータベースよりも高速にデータを読み書きできる。
ただし、メモリ上にしかデータを保存しないため、アプリケーションが終了したりシステムが再起動されたりすると、データが失わる。
組み込みデータベース
アプリケーション内部に組み込まれ、アプリケーションと一緒に実行されるデータベースであり、アプリケーションから直接アクセス可能である。
通常、永続的なストレージ(ディスクやファイル)にデータを保存する機能を持っている。
spring.sql.init.modeの機能
Spring Boot公式ドキュメント(使い方一覧-データの初期化)にはデータベースの初期化に関して以下の記載がある。
デフォルトでは、SQL データベースの初期化は、組み込みのメモリ内データベースを使用する場合にのみ実行されます。SQL データベースをその型に関係なく常に初期化するには、spring.sql.init.mode を always に設定します。同様に、初期化を無効にするには、spring.sql.init.mode を never に設定します。
また、Spring Boot公式ドキュメント(API一覧)で以下のように記載がある。
抽出したので分かりづらいが、spring.sql.init.mode
のデフォルトはembedded
であり、組み込みデータベースに対してはSQLスクリプト(私の環境ではschema.sql
とdata.sql
)による初期化を実施するということを意味していると思われる。
H2DBのモード設定
H2DBではモード指定がない場合、デフォルトではインメモリモードで設定される。組み込みモードで使用する場合には、application.propertiesにてJDBC URLにファイルパスを指定する必要がある。具体的には以下の検証を参照されたい。
実例での検証
私のあるプロジェクトでは以下のような設定でテストを実施している。
spring.sql.init.mode=always
spring.datasource.url=jdbc:h2:~/test;MODE=MySQL
spring.datasource.username=sa
spring.datasource.password=sa
spring.datasource.driver-class-name=org.h2.Driver
spring.h2.console.enabled=true
冒頭で記載したように、spring.sql.init.mode=always
があってもなくても関係ないと勘違いしたのは下記の理由による。
H2DBのモード設定で述べた通り、
spring.datasource.url=jdbc:h2:~/test;MODE=MySQL
で、H2DBを組み込みモードに設定しているため、spring.sql.init.mode=always
がない場合でもspring.sql.init.mode=embedded
が設定されているためにH2DBの初期化が毎回行われていたということである。
ちなみに、spring.datasource.url=jdbc:h2:~/test;MODE=MySQL
では、CドライブのUSERディレクトリにtest.db
というファイルが作成される(エクスプローラで確認済)。