データベースの初期化
SQL データベースは、スタックの種類に応じてさまざまな方法で初期化できます。もちろん、データベースが別のプロセスであれば、手動で行うこともできます。スキーマ生成には単一のメカニズムを使用することをお勧めします。
Hibernate を使用したデータベースの初期化
spring.jpa.hibernate.ddl-auto
を設定すると、Hibernate のデータベース初期化を制御できます。サポートされる値は none
、validate
、update
、create
、create-drop
です。Spring Boot は、組み込みデータベースを使用しているかどうかに基づいてデフォルト値を選択します。組み込みデータベースは、Connection
型と JDBC URL を見て識別されます。hsqldb
、h2
、または derby
は組み込みデータベースで、その他は組み込みデータベースではありません。組み込みデータベースが識別され、スキーママネージャー (Flyway または Liquibase) が検出されなかった場合、ddl-auto
はデフォルトで create-drop
になります。それ以外の場合は、デフォルトで none
になります。
インメモリから「実際の」データベースに切り替えるときは、新しいプラットフォームにテーブルとデータが存在することを前提としないように注意してください。ddl-auto
を明示的に設定するか、他のメカニズムのいずれかを使用してデータベースを初期化する必要があります。
org.hibernate.SQL ロガーを有効にすることで、スキーマの作成を出力できます。デバッグモードを有効にすると、これが自動的に行われます。 |
さらに、Hibernate が最初からスキーマを作成する場合(つまり、ddl-auto
プロパティが create
または create-drop
に設定される場合)、クラスパスのルートにある import.sql
という名前のファイルが起動時に実行されます。これは、デモや、慎重にテストする場合に役立ちますが、おそらく本番環境のクラスパスに配置したいものではありません。これは Hibernate 機能です(Spring とは関係ありません)。
基本的な SQL スクリプトを使用してデータベースを初期化する
Spring Boot は、JDBC DataSource
または R2DBC ConnectionFactory
のスキーマ (DDL スクリプト) を自動的に作成し、そのデータ (DML スクリプト) を初期化できます。
デフォルトでは、スキーマスクリプトは optional:classpath*:schema.sql
からロードされ、データスクリプトは optional:classpath*:data.sql
からロードされます。これらのスキーマスクリプトとデータスクリプトの場所は、それぞれ spring.sql.init.schema-locations
と spring.sql.init.data-locations
を使用してカスタマイズできます。optional:
プレフィックスは、ファイルが存在しない場合でもアプリケーションが開始されることを意味します。ファイルが存在しないときにアプリケーションを起動できないようにするには、optional:
プレフィックスを削除します。
さらに、Spring Boot は optional:classpath*:schema-${platform}.sql
および optional:classpath*:data-${platform}.sql
ファイル (存在する場合) を処理します。ここで、${platform}
は spring.sql.init.platform
の値です。これにより、必要に応じてデータベース固有のスクリプトに切り替えることができます。例: データベースのベンダー名 (hsqldb
、h2
、oracle
、mysql
、postgresql
など) に設定することを選択できます。
デフォルトでは、SQL データベースの初期化は、組み込みのメモリ内データベースを使用する場合にのみ実行されます。SQL データベースをその型に関係なく常に初期化するには、spring.sql.init.mode
を always
に設定します。同様に、初期化を無効にするには、spring.sql.init.mode
を never
に設定します。デフォルトでは、Spring Boot はスクリプトベースのデータベース初期化機能のフェイルファスト機能を有効にします。つまり、スクリプトによって例外が発生すると、アプリケーションは起動に失敗します。spring.sql.init.continue-on-error
を設定することで、その動作を調整できます。
スクリプトベースの DataSource
初期化は、デフォルトで、JPA EntityManagerFactory
Bean が作成される前に実行されます。schema.sql
を使用して JPA 管理エンティティのスキーマを作成し、data.sql
を使用してスキーマを設定できます。複数のデータソース初期化テクノロジを使用することはお勧めしませんが、スクリプトベースの DataSource
初期化を Hibernate によって実行されるスキーマ作成に基づいて構築できるようにする場合は、spring.jpa.defer-datasource-initialization
を true
に設定します。これにより、EntityManagerFactory
Bean が作成および初期化されるまで、データソースの初期化が延期されます。次に、schema.sql
を使用して、Hibernate によって実行されるスキーマ作成に追加を行うことができ、data.sql
を使用してそれを設定できます。
初期化スクリプトは、単一行コメントの -- とブロックコメントの /* */ をサポートします。他のコメント形式はサポートされていません。 |
Flyway や Liquibase などの高レベルのデータベース移行ツールを使用している場合は、スキーマの作成と初期化に単独で使用する必要があります。基本的な schema.sql
および data.sql
スクリプトを Flyway または Liquibase と一緒に使用することは推奨されておらず、将来のリリースではサポートが削除される予定です。
Spring Batch データベースを初期化する
Spring Batch を使用する場合、ほとんどの一般的なデータベースプラットフォーム用の SQL 初期化スクリプトがあらかじめパッケージ化されています。Spring Boot は、データベース型を検出し、起動時にこれらのスクリプトを実行できます。組み込みデータベースを使用する場合、これはデフォルトで行われます。次の例に示すように、任意のデータベース型に対して有効にすることもできます。
プロパティ
YAML
spring.batch.jdbc.initialize-schema=always
spring:
batch:
jdbc:
initialize-schema: "always"
spring.batch.jdbc.initialize-schema
を never
に設定することにより、初期化を明示的にオフにすることもできます。
高レベルのデータベース移行ツールを使用する
Spring Boot は、Flyway (英語) と Liquibase (英語) の 2 つの高レベルの移行ツールをサポートしています。
起動時に Flyway データベース移行を実行する
起動時に Flyway データベース移行を自動的に実行するには、適切な Flyway モジュールをクラスパスに追加します。インメモリおよびファイルベースのデータベースは org.flywaydb:flyway-core
によってサポートされています。それ以外の場合は、データベース固有のモジュールが必要です。例: PostgreSQL では org.flywaydb:flyway-database-postgresql
を使用し、MySQL では org.flywaydb:flyway-mysql
を使用します。詳細については、Flyway ドキュメント (英語) を参照してください。
通常、移行は V<VERSION>__<NAME>.sql
という形式のスクリプトです(<VERSION>
は、"1" や "2_1" などのアンダースコアで区切られたバージョンです)。デフォルトでは、これらは classpath:db/migration
と呼ばれるディレクトリにありますが、spring.flyway.locations
を設定することでその場所を変更できます。これは、1 つ以上の classpath:
または filesystem:
ロケーションのコンマ区切りリストです。例: 次の構成では、デフォルトのクラスパスの場所と /opt/migration
ディレクトリの両方でスクリプトを検索します。
プロパティ
YAML
spring.flyway.locations=classpath:db/migration,filesystem:/opt/migration
spring:
flyway:
locations: "classpath:db/migration,filesystem:/opt/migration"
特別な {vendor}
プレースホルダーを追加して、ベンダー固有のスクリプトを使用することもできます。以下を想定します。
プロパティ
YAML
spring.flyway.locations=classpath:db/migration/{vendor}
spring:
flyway:
locations: "classpath:db/migration/{vendor}"
db/migration
を使用するのではなく、前述の構成では、データベースの型(MySQL の db/migration/mysql
など)に従って使用するディレクトリを設定します。サポートされているデータベースのリストは、DatabaseDriver
(Javadoc) で入手できます。
移行は Java で作成することもできます。Flyway は、JavaMigration
を実装する Bean で自動構成されます。
FlywayProperties
(Javadoc) は、Flyway のほとんどの設定と、移行を無効にするか、場所の確認をオフにするために使用できる追加プロパティの小さなセットを提供します。構成をさらに制御する必要がある場合は、FlywayConfigurationCustomizer
Bean の登録を検討してください。
Spring Boot は Flyway.migrate()
を呼び出して、データベースの移行を実行します。さらに制御したい場合は、FlywayMigrationStrategy
(Javadoc) を実装する @Bean
を提供してください。
Flyway は SQL および Java コールバック (英語) をサポートします。SQL ベースのコールバックを使用するには、コールバックスクリプトを classpath:db/migration
ディレクトリに配置します。Java ベースのコールバックを使用するには、Callback
を実装する 1 つ以上の Bean を作成します。このような Bean は Flyway
に自動的に登録されます。@Order
を使用するか、Ordered
を実装することでオーダーできます。非推奨の FlywayCallback
インターフェースを実装する Bean も検出できますが、Callback
Bean と一緒に使用することはできません。
デフォルトでは、Flyway はコンテキストで(@Primary
) DataSource
をオートワイヤーし、それを移行に使用します。別の DataSource
を使用する場合は、作成して、その @Bean
を @FlywayDataSource
としてマークできます。そのようにして 2 つのデータソースが必要な場合は、別のデータソースを作成して @Primary
としてマークしてください。または、外部プロパティで spring.flyway.[url,user,password]
を設定することにより、Flyway のネイティブ DataSource
を使用できます。spring.flyway.url
または spring.flyway.user
のいずれかを設定するだけで、Flyway が独自の DataSource
を使用できます。3 つのプロパティのいずれかが設定されていない場合、同等の spring.datasource
プロパティの値が使用されます。
Flyway を使用して、特定のシナリオのデータを提供することもできます。例: テスト固有の移行を src/test/resources
に配置できます。これらの移行は、テストのためにアプリケーションが開始されたときにのみ実行されます。また、特定のプロファイルがアクティブな場合にのみ特定の移行が実行されるように、プロファイル固有の構成を使用して spring.flyway.locations
をカスタマイズできます。例: application-dev.properties
では、次の設定を指定できます。
プロパティ
YAML
spring.flyway.locations=classpath:/db/migration,classpath:/dev/db/migration
spring:
flyway:
locations: "classpath:/db/migration,classpath:/dev/db/migration"
その設定では、dev/db/migration
の移行は、dev
プロファイルがアクティブな場合にのみ実行されます。
起動時に Liquibase データベース移行を実行する
起動時に Liquibase データベースの移行を自動的に実行するには、org.liquibase:liquibase-core
をクラスパスに追加します。
|
デフォルトでは、マスター変更ログは db/changelog/db.changelog-master.yaml
から読み取られますが、spring.liquibase.change-log
を設定することで場所を変更できます。Liquibase は、YAML に加えて、JSON、XML、SQL 変更ログ形式もサポートしています。
デフォルトでは、Liquibase はコンテキスト内で (@Primary
) DataSource
を自動接続し、それを移行に使用します。別の DataSource
を使用する必要がある場合は、それを作成し、その @Bean
を @LiquibaseDataSource
としてマークできます。その場合、2 つのデータソースが必要な場合は、別のデータソースを作成し、それを @Primary
としてマークすることを忘れないでください。または、外部プロパティで spring.liquibase.[driver-class-name,url,user,password]
を設定することにより、Liquibase のネイティブ DataSource
を使用することもできます。spring.liquibase.url
または spring.liquibase.user
のいずれかを設定するだけで、Liquibase は独自の DataSource
を使用します。3 つのプロパティのいずれかが設定されていない場合は、同等の spring.datasource
プロパティの値が使用されます。
コンテキスト、デフォルトスキーマなどの利用可能な設定の詳細については、LiquibaseProperties
(Javadoc) を参照してください。
テストのみの移行には Flyway を使用する
テストデータベースにデータを取り込む Flyway 移行を作成する場合は、src/test/resources/db/migration
に配置します。たとえば、src/test/resources/db/migration/V9999__test-data.sql
という名前のファイルは、本番環境の移行後、テストを実行している場合にのみ実行されます。このファイルを使用して、必要なテストデータを作成できます。このファイルは、uber jar またはコンテナーにはパッケージ化されません。
テストのみの移行には Liquibase を使用する
テストデータベースにデータを入力する Liquibase 移行を作成する場合は、本番環境の変更ログも含むテスト変更ログを作成する必要があります。
まず、テストを実行するときに別の変更ログを使用するように Liquibase を構成する必要があります。これを行う 1 つの方法は、Spring Boot test
プロファイルを作成し、そこに Liquibase プロパティを配置することです。そのためには、src/test/resources/application-test.properties
という名前のファイルを作成し、そこに次のプロパティを配置します。
プロパティ
YAML
spring.liquibase.change-log=classpath:/db/changelog/db.changelog-test.yaml
spring:
liquibase:
change-log: "classpath:/db/changelog/db.changelog-test.yaml"
これにより、test
プロファイルで実行するときに、Liquibase が異なる変更ログを使用するように構成されます。
ここで、src/test/resources/db/changelog/db.changelog-test.yaml
に変更ログファイルを作成します。
databaseChangeLog:
- include:
file: classpath:/db/changelog/db.changelog-master.yaml
- changeSet:
runOrder: "last"
id: "test"
changes:
# Insert your changes here
この変更ログはテストの実行時に使用され、uber jar またはコンテナーにはパッケージ化されません。これには運用変更ログが含まれており、新しい変更セットを宣言します。runOrder: last
設定では、すべての運用変更セットが実行された後に実行されるように指定されています。たとえば、挿入チェンジセット (英語) を使用してデータを挿入したり、SQL チェンジセット (英語) を使用して SQL を直接実行したりできるようになりました。
最後に、テストの実行時に test
プロファイルをアクティブにするように Spring Boot を構成します。これを行うには、@ActiveProfiles("test")
アノテーションを @SpringBootTest
アノテーション付きテストクラスに追加します。
初期化されたデータベースに依存する
データベースの初期化は、アプリケーションがアプリケーションコンテキストのリフレッシュの一部として起動しているときに実行されます。起動時に初期化されたデータベースにアクセスできるようにするために、データベース初期化子として機能する Bean と、データベースの初期化が必要な Bean が自動的に検出されます。初期化が初期化されたデータベースに依存する Bean は、データベースを初期化する Bean に依存するように構成されます。起動時に、アプリケーションがデータベースにアクセスしようとして初期化されていない場合は、データベースを初期化し、データベースの初期化を要求する Bean の追加検出を構成できます。
データベースイニシャライザーを検出する
Spring Boot は、SQL データベースを初期化する次の型の Bean を自動的に検出します。
DataSourceScriptDatabaseInitializer
EntityManagerFactory
Flyway
FlywayMigrationInitializer
R2dbcScriptDatabaseInitializer
SpringLiquibase
データベース初期化ライブラリにサードパーティのスターターを使用している場合は、他の型の Bean も自動的に検出されるようにディテクターを提供する場合があります。他の Bean を検出するには、DatabaseInitializerDetector
の実装を META-INF/spring.factories
に登録します。
データベースの初期化に依存する Bean を検出する
Spring Boot は、データベースの初期化に依存する次の型の Bean を自動的に検出します。
AbstractEntityManagerFactoryBean
(spring.jpa.defer-datasource-initialization
がtrue
に設定されていない限り)DSLContext
(jOOQ)EntityManagerFactory
(spring.jpa.defer-datasource-initialization
がtrue
に設定されていない限り)JdbcOperations
NamedParameterJdbcOperations
サードパーティのスターターデータアクセスライブラリを使用している場合は、他の型の Bean も自動的に検出されるようにディテクターを提供する場合があります。他の Bean を検出するには、DependsOnDatabaseInitializationDetector
の実装を META-INF/spring.factories
に登録します。または、Bean のクラスまたはその @Bean
メソッドに @DependsOnDatabaseInitialization
アノテーションを付けます。