データアクセス

Spring Boot には、データソースを操作するためのスタータが多数含まれています。このセクションでは、その方法に関する質問に回答します。

カスタム DataSource を構成する

独自の DataSource (標準 Javadoc) を設定するには、その型の @Bean (Javadoc) を設定で定義します。Spring Boot は、データベースの初期化など、必要な場所で DataSource (標準 Javadoc) を再利用します。一部の設定を外部化する必要がある場合は、DataSource (標準 Javadoc) を環境にバインドできます ( サードパーティの構成を参照)。

次の例は、Bean でデータソースを定義する方法を示しています。

  • Java

  • Kotlin

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {

	@Bean
	@ConfigurationProperties(prefix = "app.datasource")
	public SomeDataSource dataSource() {
		return new SomeDataSource();
	}

}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyDataSourceConfiguration {

	@Bean
	@ConfigurationProperties(prefix = "app.datasource")
	fun dataSource(): SomeDataSource {
		return SomeDataSource()
	}

}

次の例は、プロパティを設定してデータソースを定義する方法を示しています。

  • プロパティ

  • YAML

app.datasource.url=jdbc:h2:mem:mydb
app.datasource.username=sa
app.datasource.pool-size=30
app:
  datasource:
    url: "jdbc:h2:mem:mydb"
    username: "sa"
    pool-size: 30

SomeDataSource に URL、ユーザー名、プールサイズの通常の JavaBean プロパティがあると仮定すると、これらの設定は、DataSource (標準 Javadoc) が他のコンポーネントで使用できるようになる前に自動的にバインドされます。

Spring Boot は、標準データソースの 1 つ (クラスパス上にある場合) を作成するために使用できる、DataSourceBuilder (Javadoc) と呼ばれるユーティリティビルダークラスも提供します。ビルダーは、クラスパスで使用可能なものに基づいて、使用するデータソースを検出できます。また、JDBC URL に基づいてドライバーを自動検出します。

次の例は、DataSourceBuilder (Javadoc) を使用してデータソースを作成する方法を示しています。

  • Java

  • Kotlin

import javax.sql.DataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {

	@Bean
	@ConfigurationProperties("app.datasource")
	public DataSource dataSource() {
		return DataSourceBuilder.create().build();
	}

}
import javax.sql.DataSource

import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyDataSourceConfiguration {

	@Bean
	@ConfigurationProperties("app.datasource")
	fun dataSource(): DataSource {
		return DataSourceBuilder.create().build()
	}

}

その DataSource (標準 Javadoc) を使用してアプリを実行するには、接続情報だけが必要です。プール固有の設定も提供できます。詳細については、実行時に使用される実装を確認してください。

次の例は、プロパティを設定して JDBC データソースを定義する方法を示しています。

  • プロパティ

  • YAML

app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
app:
  datasource:
    url: "jdbc:mysql://localhost/test"
    username: "dbuser"
    password: "dbpass"
    pool-size: 30

ただし、メソッドの戻り値の型が DataSource (標準 Javadoc) であるため、問題があります。これにより、接続プールの実際の型が非表示になるため、カスタム DataSource (標準 Javadoc) の構成プロパティメタデータは生成されず、IDE で自動補完は使用できません。この問題を解決するには、ビルダーの type(Class) メソッドを使用して、構築する DataSource (標準 Javadoc) の型を指定し、メソッドの戻り値の型を更新します。例: 以下は、DataSourceBuilder (Javadoc) を使用して HikariDataSource (英語) を作成する方法を示しています。

  • Java

  • Kotlin

import com.zaxxer.hikari.HikariDataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {

	@Bean
	@ConfigurationProperties("app.datasource")
	public HikariDataSource dataSource() {
		return DataSourceBuilder.create().type(HikariDataSource.class).build();
	}

}
import com.zaxxer.hikari.HikariDataSource
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyDataSourceConfiguration {

	@Bean
	@ConfigurationProperties("app.datasource")
	fun dataSource(): HikariDataSource {
		return DataSourceBuilder.create().type(HikariDataSource::class.java).build()
	}

}

残念ながら、Hikari には url プロパティがないため、この基本設定は機能しません。代わりに、jdbc-url プロパティがあるため、構成を次のように書き換える必要があります。

  • プロパティ

  • YAML

app.datasource.jdbc-url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
app:
  datasource:
    jdbc-url: "jdbc:mysql://localhost/test"
    username: "dbuser"
    password: "dbpass"
    pool-size: 30

この問題に対処するには、url から jdbc-url への変換を処理する DataSourceProperties (Javadoc) を使用します。initializeDataSourceBuilder() メソッドを使用して、任意の DataSourceProperties (Javadoc) オブジェクトの状態から DataSourceBuilder (Javadoc) を初期化できます。Spring Boot が自動的に作成する DataSourceProperties (Javadoc) を挿入することもできますが、そうすると構成が spring.datasource.* と app.datasource.* に分割されます。これを回避するには、次の例に示すように、カスタム構成プロパティプレフィックスを使用してカスタム DataSourceProperties (Javadoc) を定義します。

  • Java

  • Kotlin

import com.zaxxer.hikari.HikariDataSource;

import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration(proxyBeanMethods = false)
public class MyDataSourceConfiguration {

	@Bean
	@Primary
	@ConfigurationProperties("app.datasource")
	public DataSourceProperties dataSourceProperties() {
		return new DataSourceProperties();
	}

	@Bean
	@ConfigurationProperties("app.datasource.configuration")
	public HikariDataSource dataSource(DataSourceProperties properties) {
		return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
	}

}
import com.zaxxer.hikari.HikariDataSource
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary

@Configuration(proxyBeanMethods = false)
class MyDataSourceConfiguration {

	@Bean
	@Primary
	@ConfigurationProperties("app.datasource")
	fun dataSourceProperties(): DataSourceProperties {
		return DataSourceProperties()
	}

	@Bean
	@ConfigurationProperties("app.datasource.configuration")
	fun dataSource(properties: DataSourceProperties): HikariDataSource {
		return properties.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
	}

}

この設定は、プールの型がコードで指定され、その設定が app.datasource.configuration.* プロパティとして公開されることを除いて、Spring Boot がデフォルトで行うことと同じです。DataSourceProperties (Javadoc) は url から jdbc-url への変換を処理するため、次のように構成できます。

  • プロパティ

  • YAML

app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.configuration.maximum-pool-size=30
app:
  datasource:
    url: "jdbc:mysql://localhost/test"
    username: "dbuser"
    password: "dbpass"
    configuration:
      maximum-pool-size: 30

カスタム構成ではコード内で Hikari を使用するように指定されているため、app.datasource.type は効果がないことに注意してください。

サポートされている接続プールで説明したように、DataSourceBuilder (Javadoc) はいくつかの異なる接続プールをサポートしています。Hikari 以外のプールを使用するには、そのプールをクラスパスに追加し、type(Class) メソッドを使用して使用するプールクラスを指定し、一致するように @Bean (Javadoc) メソッドの戻り値の型を更新します。これにより、選択した特定の接続プールの構成プロパティメタデータも提供されます。

Spring Boot は、Hikari 固有の設定を spring.datasource.hikari に公開します。この例では複数のデータソース実装をサポートしていないため、この例ではより一般的な configuration サブ名前空間を使用します。

詳細については、DataSource を構成するおよび DataSourceAutoConfiguration [GitHub] (英語) クラスを参照してください。

2 つの DataSources を構成する

追加の DataSource (標準 Javadoc) を定義するには、前のセクションと同様のアプローチを使用できます。重要な違いは、DataSource (標準 Javadoc) @Bean (Javadoc) を defaultCandidate=false で宣言する必要があることです。これにより、自動構成された DataSource (標準 Javadoc) がバックオフするのを防ぎます。

Spring Framework リファレンスドキュメントではこの機能についてさらに詳しく説明しています。

追加の DataSource (標準 Javadoc) を必要な場所に挿入できるようにするには、次の例に示すように、@Qualifier (Javadoc) もアノテーション付けします。

  • Java

  • Kotlin

import com.zaxxer.hikari.HikariDataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyAdditionalDataSourceConfiguration {

	@Qualifier("second")
	@Bean(defaultCandidate = false)
	@ConfigurationProperties("app.datasource")
	public HikariDataSource secondDataSource() {
		return DataSourceBuilder.create().type(HikariDataSource.class).build();
	}

}
import com.zaxxer.hikari.HikariDataSource

import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyAdditionalDataSourceConfiguration {

	@Qualifier("second")
	@Bean(defaultCandidate = false)
	@ConfigurationProperties("app.datasource")
	fun secondDataSource(): HikariDataSource {
		return DataSourceBuilder.create().type(HikariDataSource::class.java).build()
	}

}

追加の DataSource (標準 Javadoc) を消費するには、インジェクションポイントに同じ @Qualifier (Javadoc) をアノテーション付けします。

自動構成されたデータソースと追加のデータソースは、次のように構成できます。

  • プロパティ

  • YAML

spring.datasource.url=jdbc:mysql://localhost/first
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.configuration.maximum-pool-size=30
app.datasource.url=jdbc:mysql://localhost/second
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.max-total=30
spring:
  datasource:
    url: "jdbc:mysql://localhost/first"
    username: "dbuser"
    password: "dbpass"
    configuration:
      maximum-pool-size: 30
app:
  datasource:
    url: "jdbc:mysql://localhost/second"
    username: "dbuser"
    password: "dbpass"
    max-total: 30

自動構成された DataSource (標準 Javadoc) のより高度で実装固有の構成は、spring.datasource.configuration.* プロパティを通じて利用できます。次の例に示すように、同じ概念を追加の DataSource (標準 Javadoc) にも適用できます。

  • Java

  • Kotlin

import com.zaxxer.hikari.HikariDataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyCompleteAdditionalDataSourceConfiguration {

	@Qualifier("second")
	@Bean(defaultCandidate = false)
	@ConfigurationProperties("app.datasource")
	public DataSourceProperties secondDataSourceProperties() {
		return new DataSourceProperties();
	}

	@Qualifier("second")
	@Bean(defaultCandidate = false)
	@ConfigurationProperties("app.datasource.configuration")
	public HikariDataSource secondDataSource(
			@Qualifier("secondDataSourceProperties") DataSourceProperties secondDataSourceProperties) {
		return secondDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
	}

}
import com.zaxxer.hikari.HikariDataSource

import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyCompleteAdditionalDataSourceConfiguration {

	@Qualifier("second")
	@Bean(defaultCandidate = false)
	@ConfigurationProperties("app.datasource")
	fun secondDataSourceProperties(): DataSourceProperties {
		return DataSourceProperties()
	}

	@Qualifier("second")
	@Bean(defaultCandidate = false)
	@ConfigurationProperties("app.datasource.configuration")
	fun secondDataSource(secondDataSourceProperties: DataSourceProperties): HikariDataSource {
		return secondDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
	}

}

上記の例では、Spring Boot が自動構成で使用するのと同じロジックを使用して追加のデータソースを構成します。app.datasource.configuration.* プロパティは、選択した実装に基づいて高度な設定を提供することに注意してください。

単一のカスタム DataSource を構成すると同様に、DataSource (標準 Javadoc) Bean の 1 つまたは両方の型は、DataSourceBuilder (Javadoc) の type(Class) メソッドを使用してカスタマイズできます。サポートされている型の詳細については、サポートされている接続プールを参照してください。

Spring Data リポジトリを使用する

Spring Data は、さまざまなフレーバーの Repository (Javadoc) インターフェースの実装を作成できます。Repository (Javadoc) 実装が自動構成パッケージの 1 つ (通常は、@SpringBootApplication (Javadoc) または @EnableAutoConfiguration (Javadoc) でアノテーションが付けられたメインアプリケーションクラスのパッケージ (またはサブパッケージ)) に含まれている限り、Spring Boot がそのすべてを処理します。

多くのアプリケーションでは、クラスパスに適切な Spring Data 依存関係を配置するだけで済みます。サポートされているテクノロジには、JPA 用の spring-boot-starter-data-jpa、Mongodb 用の spring-boot-starter-data-mongodb、その他さまざまなスターターがあります。まずは、@Entity (英語) オブジェクトを処理するリポジトリインターフェースをいくつか作成します。

Spring Boot は、自動構成パッケージをスキャンして、Repository (Javadoc) 実装の場所を決定します。より詳細な制御を行うには、Spring Data の @Enable … Repositories アノテーションを使用します。

Spring Data の詳細については、Spring Data プロジェクトページを参照してください。

Spring 構成から @Entity 定義を分離する

Spring Boot は、自動構成パッケージをスキャンして、@Entity (英語) 定義の場所を決定します。さらに制御するには、次の例に示すように、@EntityScan (Javadoc) アノテーションを使用します。

  • Java

  • Kotlin

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@EntityScan(basePackageClasses = City.class)
public class MyApplication {

	// ...

}
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@EntityScan(basePackageClasses = [City::class])
class MyApplication {

	// ...

}

スキャンされた @Entity 定義をフィルターする

ManagedClassNameFilter (Javadoc) Bean を使用して @Entity (英語) 定義をフィルタリングすることができます。これは、使用可能なエンティティのサブセットのみを考慮する必要があるテストで役立ちます。次の例では、com.example.app.customer パッケージのエンティティのみが含まれます。

  • Java

  • Kotlin

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.persistenceunit.ManagedClassNameFilter;

@Configuration(proxyBeanMethods = false)
public class MyEntityScanConfiguration {

	@Bean
	public ManagedClassNameFilter entityScanFilter() {
		return (className) -> className.startsWith("com.example.app.customer.");
	}

}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.orm.jpa.persistenceunit.ManagedClassNameFilter

@Configuration(proxyBeanMethods = false)
class MyEntityScanConfiguration {

	@Bean
	fun entityScanFilter() : ManagedClassNameFilter {
		return ManagedClassNameFilter { className ->
			className.startsWith("com.example.app.customer.")
		}
	}
}

JPA プロパティの構成

Spring Data JPA は、ベンダーに依存しないいくつかの構成オプション(SQL ロギングのオプションなど)をすでに提供しており、Spring Boot はそれらのオプションと Hibernate のいくつかを外部構成プロパティとして公開しています。それらの一部はコンテキストに従って自動的に検出されるため、設定する必要はありません。

spring.jpa.hibernate.ddl-auto は特殊なケースで、実行時の状況に応じてデフォルトが異なります。組み込みデータベースが使用され、スキーママネージャー (Liquibase や Flyway など) が DataSource (標準 Javadoc) を処理していない場合、デフォルトは create-drop になります。それ以外の場合は、デフォルトは none になります。

使用するダイアレクトは JPA プロバイダーによって検出されます。ダイアレクトを自分で設定する場合は、spring.jpa.database-platform プロパティを設定します。

設定する最も一般的なオプションを次の例に示します。

  • プロパティ

  • YAML

spring.jpa.hibernate.naming.physical-strategy=com.example.MyPhysicalNamingStrategy
spring.jpa.show-sql=true
spring:
  jpa:
    hibernate:
      naming:
        physical-strategy: "com.example.MyPhysicalNamingStrategy"
    show-sql: true

さらに、ローカル EntityManagerFactory (英語) が作成されるときに、spring.jpa.properties.* 内のすべてのプロパティが通常の JPA プロパティ (プレフィックスが削除された状態) として渡されます。

spring.jpa.properties.* で定義された名前が、JPA プロバイダーが期待する名前と正確に一致することを確認する必要があります。Spring Boot は、これらのエントリに対して緩いバインディングを試みません。

例: Hibernate のバッチサイズを設定する場合は、spring.jpa.properties.hibernate.jdbc.batch_size を使用する必要があります。batchSize や batch-size などの他のフォームを使用する場合、Hibernate は設定を適用しません。

Hibernate プロパティに高度なカスタマイズを適用する必要がある場合は、EntityManagerFactory (英語) を作成する前に呼び出される HibernatePropertiesCustomizer (Javadoc) Bean を登録することを検討してください。これは、自動構成によって適用されるものよりも優先されます。

Hibernate 命名戦略の構成

Hibernate は、2 つの異なる命名戦略 (英語) を使用して、オブジェクトモデルの名前を対応するデータベース名にマップします。物理および暗黙の戦略実装の完全修飾クラス名は、それぞれ spring.jpa.hibernate.naming.physical-strategy プロパティと spring.jpa.hibernate.naming.implicit-strategy プロパティを設定することで構成できます。または、アプリケーションコンテキストで ImplicitNamingStrategy (英語) または PhysicalNamingStrategy (英語) Bean が使用可能な場合、Hibernate はそれらを使用するように自動的に構成されます。

デフォルトでは、Spring Boot は物理命名戦略を CamelCaseToUnderscoresNamingStrategy (英語) で構成します。この戦略を使用すると、すべてのドットがアンダースコアに置き換えられ、キャメルケースもアンダースコアに置き換えられます。また、デフォルトでは、すべてのテーブル名は小文字で生成されます。例: TelephoneNumber エンティティは telephone_number テーブルにマップされます。スキーマで大文字と小文字が混在する識別子が必要な場合は、次の例に示すように、カスタム CamelCaseToUnderscoresNamingStrategy (英語) Bean を定義します。

  • Java

  • Kotlin

import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyHibernateConfiguration {

	@Bean
	public CamelCaseToUnderscoresNamingStrategy caseSensitivePhysicalNamingStrategy() {
		return new CamelCaseToUnderscoresNamingStrategy() {

			@Override
			protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) {
				return false;
			}

		};
	}

}
import org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyHibernateConfiguration {

	@Bean
	fun caseSensitivePhysicalNamingStrategy(): CamelCaseToUnderscoresNamingStrategy {
		return object : CamelCaseToUnderscoresNamingStrategy() {
			override fun isCaseInsensitive(jdbcEnvironment: JdbcEnvironment): Boolean {
				return false
			}
		}
	}

}

代わりに Hibernate のデフォルトを使用する場合は、次のプロパティを設定します。

  • プロパティ

  • YAML

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring:
  jpa:
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

または、次の Bean を構成できます。

  • Java

  • Kotlin

import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
class MyHibernateConfiguration {

	@Bean
	PhysicalNamingStrategyStandardImpl caseSensitivePhysicalNamingStrategy() {
		return new PhysicalNamingStrategyStandardImpl();
	}

}
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
internal class MyHibernateConfiguration {

	@Bean
	fun caseSensitivePhysicalNamingStrategy(): PhysicalNamingStrategyStandardImpl {
		return PhysicalNamingStrategyStandardImpl()
	}

}

詳細については、HibernateJpaAutoConfiguration [GitHub] (英語) および JpaBaseConfiguration [GitHub] (英語) を参照してください。

Hibernate 2 次キャッシュを構成する

Hibernate 2 次キャッシュ (英語) は、さまざまなキャッシュプロバイダーに対して構成できます。キャッシュプロバイダーを再度検索するように Hibernate を構成するのではなく、可能な場合はコンテキストで利用可能なものを提供することをお勧めします。

JCache でこれを行うには、まずクラスパスで org.hibernate.orm:hibernate-jcache が使用可能であることを確認します。次に、次の例に示すように、HibernatePropertiesCustomizer (Javadoc) Bean を追加します。

  • Java

  • Kotlin

import org.hibernate.cache.jcache.ConfigSettings;

import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyHibernateSecondLevelCacheConfiguration {

	@Bean
	public HibernatePropertiesCustomizer hibernateSecondLevelCacheCustomizer(JCacheCacheManager cacheManager) {
		return (properties) -> properties.put(ConfigSettings.CACHE_MANAGER, cacheManager.getCacheManager());
	}

}
import org.hibernate.cache.jcache.ConfigSettings
import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer
import org.springframework.cache.jcache.JCacheCacheManager
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyHibernateSecondLevelCacheConfiguration {

	@Bean
	fun hibernateSecondLevelCacheCustomizer(cacheManager: JCacheCacheManager): HibernatePropertiesCustomizer {
		return HibernatePropertiesCustomizer { properties ->
			properties[ConfigSettings.CACHE_MANAGER] = cacheManager.cacheManager
		}
	}

}

このカスタマイザーは、アプリケーションが使用するのと同じ CacheManager (Javadoc) を使用するように Hibernate を構成します。別の CacheManager (Javadoc) インスタンスを使用することもできます。詳細については、Hibernate ユーザーガイド (英語) を参照してください。

Hibernate コンポーネントでの依存性注入の使用

デフォルトでは、Spring Boot は BeanFactory (Javadoc) を使用する BeanContainer (英語) 実装を登録し、コンバーターとエンティティリスナーが通常の依存性注入を使用できるようにします。

hibernate.resource.beans.container プロパティを削除または変更する HibernatePropertiesCustomizer (Javadoc) を登録することにより、この動作を無効にしたり調整したりできます。

カスタム EntityManagerFactory を使用する

EntityManagerFactory (英語) の構成を完全に制御するには、"entityManagerFactory" という名前の @Bean (Javadoc) を追加する必要があります。Spring Boot の自動構成では、その型の Bean が存在する場合、エンティティマネージャーがオフになります。

LocalContainerEntityManagerFactoryBean (Javadoc) の Bean を自分で作成すると、自動構成された LocalContainerEntityManagerFactoryBean (Javadoc) の作成中に適用されたカスタマイズはすべて失われます。自動構成された EntityManagerFactoryBuilder (Javadoc) を使用して、JPA およびベンダープロパティを保持するようにしてください。これは、命名戦略や DDL モードなどの構成に spring.jpa.* プロパティに依存していた場合に特に重要です。

複数の EntityManagerFactories を使用する

複数のデータソースに対して JPA を使用する必要がある場合は、データソースごとに 1 つの EntityManagerFactory (英語) が必要になる可能性があります。Spring ORM の LocalContainerEntityManagerFactoryBean (Javadoc) を使用すると、ニーズに合わせて EntityManagerFactory (英語) を構成できます。また、JpaProperties (Javadoc) を再利用して、2 番目の EntityManagerFactory (英語) の設定をバインドすることもできます。2 台目の DataSource を構成する例を基にして、次の例に示すように 2 番目の EntityManagerFactory (英語) を定義できます。

  • Java

  • Kotlin

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

@Configuration(proxyBeanMethods = false)
public class MyAdditionalEntityManagerFactoryConfiguration {

	@Qualifier("second")
	@Bean(defaultCandidate = false)
	@ConfigurationProperties("app.jpa")
	public JpaProperties secondJpaProperties() {
		return new JpaProperties();
	}

	@Qualifier("second")
	@Bean(defaultCandidate = false)
	public LocalContainerEntityManagerFactoryBean secondEntityManagerFactory(@Qualifier("second") DataSource dataSource,
			@Qualifier("second") JpaProperties jpaProperties) {
		EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(jpaProperties);
		return builder.dataSource(dataSource).packages(Order.class).persistenceUnit("second").build();
	}

	private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties jpaProperties) {
		JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(jpaProperties);
		return new EntityManagerFactoryBuilder(jpaVendorAdapter, jpaProperties.getProperties(), null);
	}

	private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
		// ... map JPA properties as needed
		return new HibernateJpaVendorAdapter();
	}

}
import javax.sql.DataSource

import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.orm.jpa.JpaVendorAdapter
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter

@Configuration(proxyBeanMethods = false)
class MyAdditionalEntityManagerFactoryConfiguration {

	@Qualifier("second")
	@Bean(defaultCandidate = false)
	@ConfigurationProperties("app.jpa")
	fun secondJpaProperties(): JpaProperties {
		return JpaProperties()
	}

	@Qualifier("second")
	@Bean(defaultCandidate = false)
	fun firstEntityManagerFactory(
		@Qualifier("second") dataSource: DataSource,
		@Qualifier("second") jpaProperties: JpaProperties
	): LocalContainerEntityManagerFactoryBean {
		val builder = createEntityManagerFactoryBuilder(jpaProperties)
		return builder.dataSource(dataSource).packages(Order::class.java).persistenceUnit("second").build()
	}

	private fun createEntityManagerFactoryBuilder(jpaProperties: JpaProperties): EntityManagerFactoryBuilder {
		val jpaVendorAdapter = createJpaVendorAdapter(jpaProperties)
		return EntityManagerFactoryBuilder(jpaVendorAdapter, jpaProperties.properties, null)
	}

	private fun createJpaVendorAdapter(jpaProperties: JpaProperties): JpaVendorAdapter {
		// ... map JPA properties as needed
		return HibernateJpaVendorAdapter()
	}

}

上記の例では、@Qualifier("second") で修飾された DataSource (標準 Javadoc) Bean を使用して EntityManagerFactory (英語) を作成します。Order と同じパッケージにあるエンティティをスキャンします。app.jpa 名前空間を使用して追加の JPA プロパティをマップすることができます。@Bean(defaultCandidate=false) を使用すると、同じ型の自動構成された Bean に干渉することなく、secondJpaProperties および secondEntityManagerFactory Bean を定義できます。

Spring Framework リファレンスドキュメントではこの機能についてさらに詳しく説明しています。

JPA アクセスが必要な追加のデータソースに対しても同様の構成を提供する必要があります。全体像を完成させるには、各 EntityManagerFactory (英語) に対しても JpaTransactionManager (Javadoc) を構成する必要があります。または、両方にまたがる JTA トランザクションマネージャーを使用できる場合もあります。

Spring Data を使用する場合は、次の例に示すように、@EnableJpaRepositories (Javadoc) をそれに応じて構成する必要があります。

  • Java

  • Kotlin

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = Order.class, entityManagerFactoryRef = "entityManagerFactory")
public class OrderConfiguration {

}
import org.springframework.context.annotation.Configuration
import org.springframework.data.jpa.repository.config.EnableJpaRepositories

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = [Order::class], entityManagerFactoryRef = "firstEntityManagerFactory")
class OrderConfiguration
  • Java

  • Kotlin

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = Customer.class, entityManagerFactoryRef = "secondEntityManagerFactory")
public class CustomerConfiguration {

}
import org.springframework.context.annotation.Configuration
import org.springframework.data.jpa.repository.config.EnableJpaRepositories

@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = [Customer::class], entityManagerFactoryRef = "secondEntityManagerFactory")
class CustomerConfiguration

従来の persistence.xml ファイルを使用する

Spring Boot は、デフォルトでは META-INF/persistence.xml を検索したり使用したりしません。従来の persistence.xml を使用する場合は、型 LocalEntityManagerFactoryBean (Javadoc) (ID は "entityManagerFactory" ) の独自の @Bean (Javadoc) を定義し、そこに永続ユニット名を設定する必要があります。

デフォルト設定については、JpaBaseConfiguration [GitHub] (英語) を参照してください。

Spring Data JPA および Mongo リポジトリを使用する

Spring Data JPA と Spring Data、Mongo はどちらも、Repository (Javadoc) 実装を自動的に作成できます。クラスパスに両方が存在する場合は、Spring Boot にどのリポジトリを作成するかを伝えるために、追加の構成を行う必要がある場合があります。最も明示的にこれを行う方法は、標準の Spring Data @EnableJpaRepositories (Javadoc) および @EnableMongoRepositories (Javadoc) アノテーションを使用して、Repository (Javadoc) インターフェースの場所を提供することです。

外部構成で自動構成されたリポジトリのオン / オフを切り替えるために使用できるフラグ (spring.data.*.repositories.enabled および spring.data.*.repositories.type) もあります。これを行うと、たとえば、Mongo リポジトリをオフにして、自動構成された MongoTemplate (Javadoc) を引き続き使用する場合に役立ちます。

他の自動構成された Spring Data リポジトリ型 (Elasticsearch、Redis など) にも、同じ障害と同じ機能が存在します。これらを操作するには、アノテーションとフラグの名前を適宜変更します。

Spring Data の Web サポートのカスタマイズ

Spring Data は、Web アプリケーションでの Spring Data リポジトリの使用を簡素化する Web サポートを提供します。Spring Boot は、その構成をカスタマイズするための spring.data.web 名前空間のプロパティを提供します。Spring Data REST を使用している場合は、代わりに spring.data.rest 名前空間のプロパティを使用する必要があることに注意してください。

Spring Data リポジトリを REST エンドポイントとして公開する

アプリケーションで Spring MVC が有効になっている場合、Spring Data REST は Repository (Javadoc) 実装を REST エンドポイントとして公開できます。

Spring Boot は、RepositoryRestConfiguration (Javadoc) をカスタマイズする一連の有用なプロパティ(spring.data.rest 名前空間から)を公開します。追加のカスタマイズを提供する必要がある場合は、RepositoryRestConfigurer (Javadoc) Bean を使用する必要があります。

カスタム RepositoryRestConfigurer (Javadoc) で順序を指定しない場合は、Spring Boot が内部で使用する順序の後に実行されます。順序を指定する必要がある場合は、0 より大きい値にしてください。

JPA によって使用されるコンポーネントを構成する

JPA が使用するコンポーネントを構成する場合は、JPA の前にコンポーネントが初期化されていることを確認する必要があります。コンポーネントが自動構成されると、Spring Boot がこれを処理します。例: Flyway が自動構成されると、Hibernate は Flyway に依存するように構成されるため、Hibernate がデータベースを使用する前に Flyway がデータベースを初期化する機会が得られます。

コンポーネントを自分で構成する場合は、必要な依存関係を設定する便利な方法として、EntityManagerFactoryDependsOnPostProcessor (Javadoc) サブクラスを使用できます。例: Elasticsearch をインデックスマネージャーとして Hibernate 検索を使用する場合、次の例に示すように、すべての EntityManagerFactory (英語) Bean を elasticsearchClient Bean に依存するように構成する必要があります。

  • Java

  • Kotlin

import jakarta.persistence.EntityManagerFactory;

import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryDependsOnPostProcessor;
import org.springframework.stereotype.Component;

/**
 * {@link EntityManagerFactoryDependsOnPostProcessor} that ensures that
 * {@link EntityManagerFactory} beans depend on the {@code elasticsearchClient} bean.
 */
@Component
public class ElasticsearchEntityManagerFactoryDependsOnPostProcessor
		extends EntityManagerFactoryDependsOnPostProcessor {

	public ElasticsearchEntityManagerFactoryDependsOnPostProcessor() {
		super("elasticsearchClient");
	}

}
import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryDependsOnPostProcessor
import org.springframework.stereotype.Component

@Component
class ElasticsearchEntityManagerFactoryDependsOnPostProcessor :
	EntityManagerFactoryDependsOnPostProcessor("elasticsearchClient")

2 つの DataSources で jOOQ を構成する

複数のデータソースで jOOQ を使用する必要がある場合は、それぞれに独自の DSLContext (英語) を作成する必要があります。詳細については、JooqAutoConfiguration [GitHub] (英語) を参照してください。

特に、JooqExceptionTranslator (Javadoc) SpringTransactionProvider (Javadoc) を再利用すると、単一の DataSource (標準 Javadoc) で自動構成が行う機能と同様の機能を提供できます。