データアクセス
Spring Boot には、データソースを操作するためのスタータが多数含まれています。このセクションでは、その方法に関する質問に回答します。
カスタム DataSource を構成する
独自の DataSource
を設定するには、その型の @Bean
を設定で定義します。Spring Boot は、データベースの初期化など、必要な場所ではどこでも DataSource
を再利用します。一部の設定を外部化する必要がある場合は、DataSource
を環境にバインドできます ( サードパーティの構成を参照)。
次の例は、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
が他のコンポーネントで使用可能になる前に自動的にバインドされます。
Spring Boot は、標準データソースの 1 つ (クラスパス上にある場合) を作成するために使用できる、DataSourceBuilder
というユーティリティビルダークラスも提供します。ビルダーは、クラスパスで使用可能なものに基づいて、使用するデータソースを検出できます。また、JDBC URL に基づいてドライバーを自動検出します。
次の例は、DataSourceBuilder
を使用してデータソースを作成する方法を示しています。
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
でアプリを実行するために必要なのは、接続情報だけです。プール固有の設定も提供できます。詳細については、実行時に使用される実装を確認してください。
次の例は、プロパティを設定して 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
のメタデータにキーが生成されず、(DataSource
インターフェースはプロパティを公開しないため) IDE で補完機能を使用できません。また、クラスパスに Hikari がある場合、Hikari には url
プロパティがない (ただし、jdbcUrl
プロパティはある) ため、この基本セットアップは機能しません。その場合は、設定を次のように書き直す必要があります。
プロパティ
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
接続プールが DataSource
ではなく専用の実装を使用して返すように強制することで、これを修正できます。実行時に実装を変更することはできませんが、オプションのリストは明示的になります。
次の例は、DataSourceBuilder
を使用して 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()
}
}
DataSourceProperties
の機能を活用することで、さらに先に進むこともできます。つまり、URL が提供されていない場合は、デフォルトの組み込みデータベースに適切なユーザー名とパスワードを提供します。任意の DataSourceProperties
オブジェクトの状態から DataSourceBuilder
を簡単に初期化できるため、Spring Boot が自動的に作成する DataSource を挿入することもできます。ただし、これにより、構成が 2 つの名前空間に分割されます。spring.datasource
上の url
、username
、password
、type
、driver
と、残りはカスタム名前空間(app.datasource
)です。これを回避するには、次の例に示すように、カスタム名前空間でカスタム DataSourceProperties
を再定義できます。
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
が url
/jdbcUrl
変換を処理するため、次のように構成できます。
プロパティ
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
Spring Boot は、Hikari 固有の設定を spring.datasource.hikari に公開します。この例では複数のデータソース実装をサポートしていないため、この例ではより一般的な configuration サブ名前空間を使用します。 |
カスタム構成では Hikari を選択するため、app.datasource.type は効果がありません。実際には、ビルダーはそこに設定する可能性のある値で初期化され、.type() の呼び出しによってオーバーライドされます。 |
詳細については、「Spring Boot の機能」セクションの DataSource を構成するおよび DataSourceAutoConfiguration
[GitHub] (英語) クラスを参照してください。
2 つの DataSources を構成する
複数のデータソースを構成する必要がある場合は、前のセクションで説明したのと同じトリックを適用できます。ただし、今後のさまざまな自動構成で型別に 1 つを取得できることが想定されるため、DataSource
インスタンスの 1 つを @Primary
としてマークする必要があります。
独自の DataSource
を作成すると、自動構成はバックオフします。次の例では、自動構成がプライマリデータソースで提供するものとまったく同じ機能セットを提供します。
Java
Kotlin
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
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;
import org.springframework.context.annotation.Primary;
@Configuration(proxyBeanMethods = false)
public class MyDataSourcesConfiguration {
@Bean
@Primary
@ConfigurationProperties("app.datasource.first")
public DataSourceProperties firstDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@Primary
@ConfigurationProperties("app.datasource.first.configuration")
public HikariDataSource firstDataSource(DataSourceProperties firstDataSourceProperties) {
return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
@Bean
@ConfigurationProperties("app.datasource.second")
public BasicDataSource secondDataSource() {
return DataSourceBuilder.create().type(BasicDataSource.class).build();
}
}
import com.zaxxer.hikari.HikariDataSource
import org.apache.commons.dbcp2.BasicDataSource
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
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
import org.springframework.context.annotation.Primary
@Configuration(proxyBeanMethods = false)
class MyDataSourcesConfiguration {
@Bean
@Primary
@ConfigurationProperties("app.datasource.first")
fun firstDataSourceProperties(): DataSourceProperties {
return DataSourceProperties()
}
@Bean
@Primary
@ConfigurationProperties("app.datasource.first.configuration")
fun firstDataSource(firstDataSourceProperties: DataSourceProperties): HikariDataSource {
return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
}
@Bean
@ConfigurationProperties("app.datasource.second")
fun secondDataSource(): BasicDataSource {
return DataSourceBuilder.create().type(BasicDataSource::class.java).build()
}
}
データベース初期化機能がコピーを使用するように、firstDataSourceProperties に @Primary のフラグを立てる必要があります(初期化を使用する場合)。 |
両方のデータソースは、高度なカスタマイズにも対応しています。たとえば、次のように構成できます。
プロパティ
YAML
app.datasource.first.url=jdbc:mysql://localhost/first
app.datasource.first.username=dbuser
app.datasource.first.password=dbpass
app.datasource.first.configuration.maximum-pool-size=30
app.datasource.second.url=jdbc:mysql://localhost/second
app.datasource.second.username=dbuser
app.datasource.second.password=dbpass
app.datasource.second.max-total=30
app:
datasource:
first:
url: "jdbc:mysql://localhost/first"
username: "dbuser"
password: "dbpass"
configuration:
maximum-pool-size: 30
second:
url: "jdbc:mysql://localhost/second"
username: "dbuser"
password: "dbpass"
max-total: 30
次の例に示すように、セカンダリ DataSource
にも同じ概念を適用できます。
Java
Kotlin
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbcp2.BasicDataSource;
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;
import org.springframework.context.annotation.Primary;
@Configuration(proxyBeanMethods = false)
public class MyCompleteDataSourcesConfiguration {
@Bean
@Primary
@ConfigurationProperties("app.datasource.first")
public DataSourceProperties firstDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@Primary
@ConfigurationProperties("app.datasource.first.configuration")
public HikariDataSource firstDataSource(DataSourceProperties firstDataSourceProperties) {
return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
@Bean
@ConfigurationProperties("app.datasource.second")
public DataSourceProperties secondDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties("app.datasource.second.configuration")
public BasicDataSource secondDataSource(
@Qualifier("secondDataSourceProperties") DataSourceProperties secondDataSourceProperties) {
return secondDataSourceProperties.initializeDataSourceBuilder().type(BasicDataSource.class).build();
}
}
import com.zaxxer.hikari.HikariDataSource
import org.apache.commons.dbcp2.BasicDataSource
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 MyCompleteDataSourcesConfiguration {
@Bean
@Primary
@ConfigurationProperties("app.datasource.first")
fun firstDataSourceProperties(): DataSourceProperties {
return DataSourceProperties()
}
@Bean
@Primary
@ConfigurationProperties("app.datasource.first.configuration")
fun firstDataSource(firstDataSourceProperties: DataSourceProperties): HikariDataSource {
return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource::class.java).build()
}
@Bean
@ConfigurationProperties("app.datasource.second")
fun secondDataSourceProperties(): DataSourceProperties {
return DataSourceProperties()
}
@Bean
@ConfigurationProperties("app.datasource.second.configuration")
fun secondDataSource(secondDataSourceProperties: DataSourceProperties): BasicDataSource {
return secondDataSourceProperties.initializeDataSourceBuilder().type(BasicDataSource::class.java).build()
}
}
前の例では、Spring Boot が自動構成で使用するのと同じロジックを使用して、カスタム名前空間に 2 つのデータソースを構成します。各 configuration
サブ名前空間は、選択した実装に基づいて高度な設定を提供することに注意してください。
Spring Data リポジトリを使用する
Spring Data は、さまざまなフレーバーの Repository
インターフェースの実装を作成できます。Repository
実装が自動構成パッケージの 1 つ (通常は、@SpringBootApplication
または @EnableAutoConfiguration
でアノテーションが付けられたメインアプリケーションクラスのパッケージ (またはサブパッケージ)) に含まれている限り、Spring Boot がそのすべてを処理します。
多くのアプリケーションでは、クラスパスに適切な Spring Data 依存関係を設定するだけで済みます。JPA 用の spring-boot-starter-data-jpa
、Mongodb 用の spring-boot-starter-data-mongodb
、サポートされているテクノロジー用の他のさまざまなスターターがあります。開始するには、@Entity
オブジェクトを処理するためのリポジトリインターフェースをいくつか作成します。
Spring Boot は、自動構成パッケージをスキャンして、Repository
実装の場所を決定します。より詳細な制御を行うには、Spring Data の @Enable … Repositories
アノテーションを使用します。
Spring Data の詳細については、Spring Data プロジェクトページを参照してください。
Spring 構成から @Entity 定義を分離する
Spring Boot は、自動構成パッケージをスキャンして、@Entity
定義の場所を特定します。さらに制御するには、次の例に示すように、@EntityScan
アノテーションを使用します。
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
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
を処理していない場合は、デフォルトで 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
また、spring.jpa.properties.*
のすべてのプロパティは、ローカル EntityManagerFactory
が作成されるときに、通常の JPA プロパティとして(プレフィックスが削除された状態で)渡されます。
例: Hibernate のバッチサイズを設定する場合は、 |
Hibernate プロパティに高度なカスタマイズを適用する必要がある場合は、EntityManagerFactory を作成する前に呼び出される HibernatePropertiesCustomizer 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
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
を使用するように Hibernate を構成します。個別の CacheManager
インスタンスを使用することもできます。詳細については、Hibernate ユーザーガイド (英語) を参照してください。
Hibernate コンポーネントでの依存性注入の使用
デフォルトでは、Spring Boot は BeanFactory
を使用する BeanContainer
実装を登録して、コンバーターとエンティティリスナーが通常の依存性注入を使用できるようにします。
hibernate.resource.beans.container
プロパティを削除または変更する HibernatePropertiesCustomizer
を登録することにより、この動作を無効化または調整できます。
カスタム EntityManagerFactory を使用する
EntityManagerFactory
の構成を完全に制御するには、"entityManagerFactory" という名前の @Bean
を追加する必要があります。Spring Boot の自動構成では、その型の Bean が存在する場合、エンティティマネージャーがオフになります。
複数の EntityManagerFactories を使用する
複数のデータソースに対して JPA を使用する必要がある場合は、データソースごとに 1 つの EntityManagerFactory
が必要になる可能性があります。Spring ORM の LocalContainerEntityManagerFactoryBean
を使用すると、ニーズに合わせて EntityManagerFactory
を構成できます。次の例に示すように、JpaProperties
を再利用して、各 EntityManagerFactory
の設定をバインドすることもできます。
Java
Kotlin
import javax.sql.DataSource;
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 MyEntityManagerFactoryConfiguration {
@Bean
@ConfigurationProperties("app.jpa.first")
public JpaProperties firstJpaProperties() {
return new JpaProperties();
}
@Bean
public LocalContainerEntityManagerFactoryBean firstEntityManagerFactory(DataSource firstDataSource,
JpaProperties firstJpaProperties) {
EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(firstJpaProperties);
return builder.dataSource(firstDataSource).packages(Order.class).persistenceUnit("firstDs").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.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 MyEntityManagerFactoryConfiguration {
@Bean
@ConfigurationProperties("app.jpa.first")
fun firstJpaProperties(): JpaProperties {
return JpaProperties()
}
@Bean
fun firstEntityManagerFactory(
firstDataSource: DataSource?,
firstJpaProperties: JpaProperties
): LocalContainerEntityManagerFactoryBean {
val builder = createEntityManagerFactoryBuilder(firstJpaProperties)
return builder.dataSource(firstDataSource).packages(Order::class.java).persistenceUnit("firstDs").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()
}
}
上記の例では、firstDataSource
という名前の DataSource
Bean を使用して EntityManagerFactory
を作成します。Order
と同じパッケージにあるエンティティをスキャンします。app.first.jpa
名前空間を使用して、追加の JPA プロパティをマップすることができます。
LocalContainerEntityManagerFactoryBean の Bean を自分で作成すると、自動構成された LocalContainerEntityManagerFactoryBean の作成中に適用されたカスタマイズはすべて失われます。例: Hibernate の場合、spring.jpa.hibernate プレフィックスのプロパティは LocalContainerEntityManagerFactoryBean に自動的に適用されません。命名戦略や DDL モードなどの構成にこれらのプロパティに依存していた場合は、LocalContainerEntityManagerFactoryBean Bean を作成するときに明示的に構成する必要があります。 |
JPA アクセスが必要な追加のデータソースについても、同様の構成を提供する必要があります。全体像を完成させるには、EntityManagerFactory
ごとに JpaTransactionManager
も構成する必要があります。または、両方にまたがる JTA トランザクションマネージャーを使用できる場合もあります。
Spring Data を使用する場合は、次の例に示すように、それに応じて @EnableJpaRepositories
を構成する必要があります。
Java
Kotlin
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration(proxyBeanMethods = false)
@EnableJpaRepositories(basePackageClasses = Order.class, entityManagerFactoryRef = "firstEntityManagerFactory")
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
(ID が "entityManagerFactory" ) の独自の @Bean
を定義し、そこに永続ユニット名を設定する必要があります。
デフォルト設定については、JpaBaseConfiguration
[GitHub] (英語) を参照してください。
Spring Data JPA および Mongo リポジトリを使用する
Spring Data JPA と Spring Data Mongo はどちらも Repository
実装を自動的に作成できます。両方がクラスパスに存在する場合は、Spring Boot に作成するリポジトリを指示するために、追加の構成が必要になる場合があります。最も明示的な方法は、標準の Spring Data @EnableJpaRepositories
および @EnableMongoRepositories
アノテーションを使用して、Repository
インターフェースの場所を提供することです。
外部構成で自動構成リポジトリのオンとオフを切り替えるために使用できるフラグ(spring.data.*.repositories.enabled
および spring.data.*.repositories.type
)もあります。これは、たとえば、Mongo リポジトリをオフにし、自動構成された MongoTemplate
を使用したい場合に役立ちます。
他の自動構成された 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
実装を REST エンドポイントとして公開できます。
Spring Boot は、RepositoryRestConfiguration
(Javadoc) をカスタマイズする一連の有用なプロパティ(spring.data.rest
名前空間から)を公開します。追加のカスタマイズを提供する必要がある場合は、RepositoryRestConfigurer
(Javadoc) Bean を使用する必要があります。
カスタム RepositoryRestConfigurer で順序を指定しない場合、Spring Boot が内部的に使用した後に実行されます。順序を指定する必要がある場合は、0 より大きいことを確認してください。 |
JPA によって使用されるコンポーネントを構成する
JPA が使用するコンポーネントを構成する場合は、JPA の前にコンポーネントが初期化されていることを確認する必要があります。コンポーネントが自動構成されると、Spring Boot がこれを処理します。例: Flyway が自動構成されると、Hibernate は Flyway に依存するように構成されるため、Hibernate がデータベースを使用する前に Flyway がデータベースを初期化する機会が得られます。
コンポーネントを自分で構成する場合は、必要な依存関係を設定する便利な方法として、EntityManagerFactoryDependsOnPostProcessor
サブクラスを使用できます。例: 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 および SpringTransactionProvider を再利用して、単一の DataSource で自動構成が行うことと同様の機能を提供できます。 |