組み込みデータベースのサポート

org.springframework.jdbc.datasource.embedded パッケージは、組み込み Java データベースエンジンのサポートを提供します。HSQL (英語) H2 (英語) Derby [Apache] (英語) のサポートはネイティブで提供されます。拡張可能な API を使用して、新しい組み込みデータベース型と DataSource 実装をプラグインすることもできます。

埋め込みデータベースを使用する理由

組み込みデータベースは、軽量であるため、プロジェクトの開発段階で役立ちます。利点には、構成の容易さ、起動時間の短縮、テスト容易性、開発中に SQL を迅速に進化させる機能が含まれます。

組み込みデータベースの作成

次の例に示すように、組み込みデータベースインスタンスを Bean として公開できます。

  • Java

  • Kotlin

  • XML

@Bean
DataSource dataSource() {
	return new EmbeddedDatabaseBuilder()
			.generateUniqueName(true)
			.setType(EmbeddedDatabaseType.H2)
			.addScripts("schema.sql", "test-data.sql")
			.build();
}
@Bean
fun dataSource() = EmbeddedDatabaseBuilder()
	.generateUniqueName(true)
	.setType(EmbeddedDatabaseType.H2)
	.addScripts("schema.sql", "test-data.sql")
	.build()
<jdbc:embedded-database id="dataSource" generate-name="true" type="H2">
	<jdbc:script location="classpath:schema.sql"/>
	<jdbc:script location="classpath:test-data.sql"/>
</jdbc:embedded-database>

前述の構成では、クラスパスのルートにある schema.sql および test-data.sql リソースからの SQL が取り込まれる組み込み H2 データベースが作成されます。さらに、ベストプラクティスとして、組み込みデータベースには一意に生成された名前が割り当てられます。組み込みデータベースは、javax.sql.DataSource 型の Bean として Spring コンテナーで利用できるようになり、必要に応じてデータアクセスオブジェクトに挿入できます。

サポートされているすべてのオプションの詳細については、EmbeddedDatabaseBuilder の javadoc を参照してください。

組み込みデータベース型の選択

このセクションでは、Spring がサポートする 3 つの組み込みデータベースのいずれかを選択する方法について説明します。次のトピックが含まれます。

HSQL を使用する

Spring は、HSQL 1.8.0 以上をサポートしています。HSQL は、型が明示的に指定されていない場合のデフォルトの組み込みデータベースです。HSQL を明示的に指定するには、embedded-database タグの type 属性を HSQL に設定します。ビルダー API を使用する場合は、EmbeddedDatabaseType.HSQL を使用して setType(EmbeddedDatabaseType) メソッドを呼び出します。

H2 を使用する

Spring は H2 データベースをサポートしています。H2 を有効にするには、embedded-database タグの type 属性を H2 に設定します。ビルダー API を使用する場合は、EmbeddedDatabaseType.H2 を使用して setType(EmbeddedDatabaseType) メソッドを呼び出します。

Derby の使用

Spring は Apache Derby 10.5 以上をサポートします。Derby を有効にするには、embedded-database タグの type 属性を DERBY に設定します。ビルダー API を使用する場合は、EmbeddedDatabaseType.DERBY で setType(EmbeddedDatabaseType) メソッドを呼び出します。

埋め込みデータベース型のカスタマイズ

サポートされている各型にはデフォルトの接続設定が付属していますが、必要に応じてカスタマイズできます。次の例では、カスタムドライバーで H2 を使用しています。

  • Java

  • Kotlin

   @Configuration
   public class DataSourceConfig {

       @Bean
       public DataSource dataSource() {
           return new EmbeddedDatabaseBuilder()
                   .setDatabaseConfigurer(EmbeddedDatabaseConfigurers
                           .customizeConfigurer(H2, this::customize))
                   .addScript("schema.sql")
                   .build();
       }

       private EmbeddedDatabaseConfigurer customize(EmbeddedDatabaseConfigurer defaultConfigurer) {
           return new EmbeddedDatabaseConfigurerDelegate(defaultConfigurer) {
               @Override
               public void configureConnectionProperties(ConnectionProperties properties, String databaseName) {
                   super.configureConnectionProperties(properties, databaseName);
                   properties.setDriverClass(CustomDriver.class);
               }
           };
       }
}
@Configuration
class DataSourceConfig {

	@Bean
	fun dataSource(): DataSource {
		return EmbeddedDatabaseBuilder()
			.setDatabaseConfigurer(EmbeddedDatabaseConfigurers
				.customizeConfigurer(EmbeddedDatabaseType.H2) { this.customize(it) })
			.addScript("schema.sql")
			.build()
	}

	private fun customize(defaultConfigurer: EmbeddedDatabaseConfigurer): EmbeddedDatabaseConfigurer {
		return object : EmbeddedDatabaseConfigurerDelegate(defaultConfigurer) {
			override fun configureConnectionProperties(
				properties: ConnectionProperties,
				databaseName: String
			) {
				super.configureConnectionProperties(properties, databaseName)
				properties.setDriverClass(CustomDriver::class.java)
			}
		}
	}
}

組み込みデータベースを使用したデータアクセスロジックのテスト

組み込みデータベースは、データアクセスコードをテストするための軽量な方法を提供します。次の例は、組み込みデータベースを使用するデータアクセス統合テストテンプレートです。このようなテンプレートの使用は、組み込みデータベースをテストクラス間で再利用する必要がない場合に 1 回限りの場合に役立ちます。ただし、テストスイート内で共有される組み込みデータベースを作成する場合は、組み込みデータベースの作成に従って、Spring TestContext フレームワークを使用し、組み込みデータベースを Spring ApplicationContext の Bean として構成することを検討してください。次のリストはテストテンプレートを示しています。

  • Java

  • Kotlin

public class DataAccessIntegrationTestTemplate {

	private EmbeddedDatabase db;

	@BeforeEach
	public void setUp() {
		// creates an HSQL in-memory database populated from default scripts
		// classpath:schema.sql and classpath:data.sql
		db = new EmbeddedDatabaseBuilder()
				.generateUniqueName(true)
				.addDefaultScripts()
				.build();
	}

	@Test
	public void testDataAccess() {
		JdbcTemplate template = new JdbcTemplate(db);
		template.query( /* ... */ );
	}

	@AfterEach
	public void tearDown() {
		db.shutdown();
	}

}
class DataAccessIntegrationTestTemplate {

	private lateinit var db: EmbeddedDatabase

	@BeforeEach
	fun setUp() {
		// creates an HSQL in-memory database populated from default scripts
		// classpath:schema.sql and classpath:data.sql
		db = EmbeddedDatabaseBuilder()
				.generateUniqueName(true)
				.addDefaultScripts()
				.build()
	}

	@Test
	fun testDataAccess() {
		val template = JdbcTemplate(db)
		template.query( /* ... */)
	}

	@AfterEach
	fun tearDown() {
		db.shutdown()
	}
}

組み込みデータベースの一意の名前の生成

開発チームは、テストスイートが誤って同じデータベースの追加インスタンスを再作成しようとすると、組み込みデータベースでエラーが発生することがよくあります。これは、XML 構成ファイルまたは @Configuration クラスが組み込みデータベースの作成を担当し、対応する構成が同じテストスイート内(つまり、同じ JVM プロセス内)の複数のテストシナリオで再利用される場合、非常に簡単に発生します。ApplicationContext 構成がアクティブである Bean 定義プロファイルに関してのみ異なる組み込みデータベースに対する統合テスト。

このようなエラーの根本的な原因は、Spring の EmbeddedDatabaseFactory (<jdbc:embedded-database> XML 名前空間要素と EmbeddedDatabaseBuilder for Java 構成の両方で内部的に使用される)が、特に指定がない限り、組み込みデータベースの名前を testdb に設定することです。<jdbc:embedded-database> の場合、組み込みデータベースには通常、Bean の id と同じ名前(多くの場合、dataSource のようなもの)が割り当てられます。埋め込みデータベースを作成しようとしても、新しいデータベースは作成されません。代わりに、同じ JDBC 接続 URL が再利用され、新しい組み込みデータベースを作成しようとすると、実際には同じ構成から作成された既存の組み込みデータベースを指します。

この一般的な課題に対処するために、Spring Framework 4.2 は組み込みデータベースの一意の名前を生成するためのサポートを提供します。生成された名前の使用を有効にするには、次のいずれかのオプションを使用します。

  • EmbeddedDatabaseFactory.setGenerateUniqueDatabaseName()

  • EmbeddedDatabaseBuilder.generateUniqueName()

  • <jdbc:embedded-database generate-name="true" …​ >

組み込みデータベースサポートの拡張

Spring JDBC 組み込みデータベースのサポートは、次の 2 つの方法で拡張できます。

  • EmbeddedDatabaseConfigurer を実装して、新しい組み込みデータベース型をサポートします。

  • DataSourceFactory を実装して、組み込みデータベース接続を管理する接続プールなどの新しい DataSource 実装をサポートします。

GitHub の課題 (英語) の Spring コミュニティに拡張機能を提供することをお勧めします。