数据访问
Spring Boot 包含许多用于处理数据源的 Starter。 本节回答与执行此操作相关的问题。
配置自定义数据源
要配置您自己的 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()
}
}
以下示例显示如何通过设置数据源的属性来定义数据源:
-
Properties
-
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
假设它具有 URL、用户名和池大小的常规 JavaBean 属性,则在 DataSource
可供其他组件使用之前,这些设置会自动绑定。SomeDataSource
Spring Boot 还提供了一个名为 DataSourceBuilder
的 Util 构建器类,该类可用于创建标准数据源之一(如果它在 Classpath 上)。
构建器可以根据 Classpath 上可用的内容来检测要使用的 Classpath。
它还会根据 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 数据源:
-
Properties
-
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 中没有可用的自动完成功能。
要解决此问题,请使用生成器的方法指定要构建的 DataSource
的类型,并更新该方法的返回类型。
例如,下面显示了如何使用 DataSourceBuilder
创建 HikariDataSource
:type(Class)
-
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
-
Properties
-
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
要解决此问题,请使用 DataSourceProperties
,它将为您处理 to 转换。
您可以使用其方法从任何 DataSourceProperties
对象的状态初始化 DataSourceBuilder
。
您可以注入 Spring Boot 自动创建的DataSourceProperties
,但是,这会将您的配置拆分为 和 。
为避免这种情况,请使用自定义配置属性前缀定义自定义 DataSourceProperties
,如以下示例所示:url
jdbc-url
initializeDataSourceBuilder()
spring.datasource.*
app.datasource.*
-
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()
}
}
此设置等效于 Spring Boot 默认为您所做的工作,不同之处在于池的类型是在代码中指定的,并且其设置作为属性公开。DataSourceProperties
负责 to 转换,因此您可以按如下方式对其进行配置:app.datasource.configuration.*
url
jdbc-url
-
Properties
-
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
支持多种不同的连接池。
要使用 Hikari 以外的池,请将其添加到 Classpath 中,使用该方法指定要使用的池类,并更新 @Bean
方法的返回类型以匹配。
这还将为您提供所选特定连接池的配置属性元数据。type(Class)
Spring Boot 会将特定于 Hikari 的设置公开给 .
此示例使用更通用的子命名空间,因为该示例不支持多个数据源实施。spring.datasource.hikari configuration |
有关更多详细信息,请参阅配置 DataSource 和 DataSourceAutoConfiguration
类。
配置两个数据源
要定义其他 DataSource
,可以使用类似于上一节的方法。
一个关键区别是 DataSource
@Bean
必须使用 .
这可以防止自动配置的 DataSource
后退。defaultCandidate=false
Spring Framework 参考文档更详细地描述了此功能。 |
要允许在需要的地方注入额外的DataSource
,还要用 @Qualifier
对其进行注释,如以下示例所示:
-
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
,请使用相同的 @Qualifier
注释注入点。
可以按如下方式配置自动配置的数据源和其他数据源:
-
Properties
-
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
的更高级、特定于实现的配置可通过 properties 获得。
您也可以将相同的概念应用于其他 DataSource
,如以下示例所示:spring.datasource.configuration.*
-
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
一样,可以使用DataSourceBuilder
上的方法自定义一个或两个DataSource
bean 的类型。
有关支持的类型的详细信息,请参阅支持的连接池。type(Class)
使用 Spring 数据存储库
Spring Data 可以创建各种风格的 Repository
接口的实现。
Spring Boot 会为你处理所有这些,只要这些 Repository
实现包含在其中一个自动配置包中,通常是用 @SpringBootApplication
或 @EnableAutoConfiguration
注释的主应用程序类的包(或子包)。
对于许多应用程序,您所需要做的就是将正确的 Spring Data 依赖项放在 Classpath 上。
有一个用于 JPA、用于 MongoDB 以及支持技术的各种其他Starters。
首先,创建一些存储库接口来处理 @Entity
对象。spring-boot-starter-data-jpa
spring-boot-starter-data-mongodb
Spring Boot 通过扫描自动配置包来确定 Repository
实现的位置。
要获得更多控制,请使用 Spring Data 中的 Comments。@Enable…Repositories
有关 Spring Data 的更多信息,请参阅 Spring Data 项目页面。
将 @Entity 定义与 Spring 配置分开
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 的更多选项公开为外部配置属性。 其中一些是根据上下文自动检测的,因此您不必设置它们。
这是一种特殊情况,因为根据运行时条件,它具有不同的默认值。
如果使用嵌入式数据库,并且没有架构管理器(例如 Liquibase 或 Flyway)正在处理 DataSource
,则它默认为 .
在所有其他情况下,它默认为 。spring.jpa.hibernate.ddl-auto
create-drop
none
要使用的方言由 JPA 提供程序检测。
如果希望自己设置方言,请设置属性。spring.jpa.database-platform
以下示例显示了要设置的最常见选项:
-
Properties
-
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
时,中的所有属性都作为普通的 JPA 属性(前缀被剥离)传递。spring.jpa.properties.*
您需要确保 下定义的名称与 JPA 提供程序预期的名称完全匹配。
Spring Boot 不会尝试对这些条目进行任何类型的松散绑定。 例如,如果要配置 Hibernate 的批处理大小,则必须使用 .
如果使用其他形式(如 或 ),则 Hibernate 将不会应用该设置。 |
如果需要对 Hibernate 属性应用高级自定义,请考虑注册一个 HibernatePropertiesCustomizer Bean,该 bean 将在创建 EntityManagerFactory 之前调用。
这优先于自动配置应用的任何内容。 |
配置 Hibernate 命名策略
Hibernate 使用两种不同的命名策略将名称从对象模型映射到相应的数据库名称。
物理和隐式策略实现的完全限定类名可以通过分别设置 和 属性来配置。
或者,如果 ImplicitNamingStrategy
或 PhysicalNamingStrategy
bean 在应用程序上下文中可用,则 Hibernate 将自动配置为使用它们。spring.jpa.hibernate.naming.physical-strategy
spring.jpa.hibernate.naming.implicit-strategy
默认情况下, Spring Boot 使用CamelCaseToUnderscoresNamingStrategy
配置物理命名策略。
使用此策略,所有点都替换为下划线,驼峰大小写也替换为下划线。
此外,默认情况下,所有表名都以小写形式生成。
例如,实体映射到表。
如果您的架构需要大小写混合标识符,请定义自定义 CamelCaseToUnderscoresNamingStrategy
Bean,如以下示例所示:TelephoneNumber
telephone_number
-
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 的默认值,请设置以下属性:
-
Properties
-
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
和JpaBaseConfiguration
。
配置 Hibernate Second-Level Caching
可以为一系列缓存提供程序配置 Hibernate 二级缓存。 与其配置 Hibernate 再次查找缓存提供程序,不如尽可能提供上下文中可用的缓存提供程序。
要使用 JCache 执行此操作,首先确保它在 Classpath 上可用。
然后,添加一个 HibernatePropertiesCustomizer
Bean,如以下示例所示:org.hibernate.orm:hibernate-jcache
-
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
}
}
}
此定制器将配置 Hibernate 以使用与应用程序使用的相同的 CacheManager
。
也可以使用单独的 CacheManager
实例。
有关详细信息,请参阅 Hibernate 用户指南。
在 Hibernate 组件中使用依赖注入
默认情况下, Spring Boot 注册一个使用 BeanFactory
的 BeanContainer
实现,以便转换器和实体侦听器可以使用常规的依赖注入。
您可以通过注册删除或更改属性的 HibernatePropertiesCustomizer
来禁用或调整此行为。hibernate.resource.beans.container
使用自定义 EntityManagerFactory
要完全控制 EntityManagerFactory
的配置,您需要添加一个名为 'entityManagerFactory' 的@Bean
。
Spring Boot 自动配置在存在该类型的 bean 时关闭其实体 manager。
当您自己为 LocalContainerEntityManagerFactoryBean 创建 Bean 时,在创建自动配置的 LocalContainerEntityManagerFactoryBean 期间应用的任何自定义都将丢失。
确保使用自动配置的 EntityManagerFactoryBuilder 来保留 JPA 和 vendor 属性。
如果您依赖属性来配置命名策略或 DDL 模式等内容,这一点尤其重要。spring.jpa.* |
使用多个 EntityManagerFactories
如果您需要对多个数据源使用 JPA,则可能需要每个数据源一个 EntityManagerFactory
。
Spring ORM 中的LocalContainerEntityManagerFactoryBean
允许你根据需要配置EntityManagerFactory
。
你也可以重用 JpaProperties
来绑定第二个 EntityManagerFactory
的设置。
基于配置第二个 DataSource
的示例,可以定义第二个 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()
}
}
上面的示例使用用
.
它扫描与数据包位于同一包中的实体。
可以使用命名空间映射其他 JPA 属性。
使用 of 允许定义 and bean,而不会干扰相同类型的自动配置的 bean。@Qualifier("second")
Order
app.jpa
@Bean(defaultCandidate=false)
secondJpaProperties
secondEntityManagerFactory
Spring Framework 参考文档更详细地描述了此功能。 |
您应该为需要 JPA 访问权限的任何其他数据源提供类似的配置。
要完成这张图片,你还需要为每个EntityManagerFactory
配置一个JpaTransactionManager
。
或者,您可以使用跨越两者的 JTA 事务 Management 器。
如果使用 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 = "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 默认情况下不会搜索或使用a。
如果您更喜欢使用传统的,则需要定义自己的 LocalEntityManagerFactoryBean
类型的@Bean
(ID 为“entityManagerFactory”)并在那里设置持久化单元名称。META-INF/persistence.xml
persistence.xml
有关默认设置,请参见JpaBaseConfiguration
。
使用 Spring Data JPA 和 Mongo 存储库
Spring Data JPA 和 Spring Data Mongo 都可以自动为您创建 Repository
实现。
如果它们都存在于 Classpath 中,则可能必须进行一些额外的配置以告诉 Spring Boot 要创建哪些存储库。
最明确的方法是使用标准的 Spring Data @EnableJpaRepositories
和 @EnableMongoRepositories
注释,并提供 Repository
接口的位置。
还有一些标志 ( 和 ) 可用于在外部配置中打开和关闭自动配置的存储库。
这样做很有用,例如,如果您想关闭 Mongo 存储库并仍然使用自动配置的 MongoTemplate
。spring.data.*.repositories.enabled
spring.data.*.repositories.type
其他自动配置的 Spring Data 存储库类型(Elasticsearch、Redis 等)存在相同的障碍和相同的功能。 要使用它们,请相应地更改注释和标志的名称。
自定义 Spring Data 的 Web 支持
Spring Data 提供 Web 支持,可简化 Spring Data 存储库在 Web 应用程序中的使用。
Spring Boot 在名称空间中提供了用于自定义其配置的属性。
请注意,如果您使用的是 Spring Data REST,则必须改用名称空间中的属性。spring.data.web
spring.data.rest
将 Spring Data Repositories 公开为 REST 端点
Spring Data REST 可以为你将 Repository
实现公开为 REST 端点,
前提是已为应用程序启用了 Spring MVC。
Spring Boot 公开了一组有用的属性(来自名称空间),用于自定义RepositoryRestConfiguration
。
如果需要提供其他自定义,则应使用RepositoryRestConfigurer
bean。spring.data.rest
如果你没有在自定义RepositoryRestConfigurer 上指定任何 order,它将在 Spring Boot 内部使用的 order 之后运行。
如果需要指定顺序,请确保顺序大于 0。 |
配置 JPA 使用的组件
如果要配置 JPA 使用的组件,则需要确保在 JPA 之前初始化该组件。 当组件被自动配置时, Spring Boot 会为你处理这个问题。 例如,当 Flyway 被自动配置时,Hibernate 被配置为依赖于 Flyway,以便 Flyway 有机会在 Hibernate 尝试使用数据库之前初始化数据库。
如果您自己配置组件,则可以使用 EntityManagerFactoryDependsOnPostProcessor
子类作为设置必要依赖项的便捷方式。
例如,如果你使用 Hibernate Search 并将 Elasticsearch 作为其索引管理器,则必须将任何 EntityManagerFactory
bean 配置为依赖于该 bean,如以下示例所示:elasticsearchClient
-
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")
使用两个数据源配置 jOOQ
如果需要将 jOOQ 与多个数据源一起使用,则应为每个数据源创建自己的 DSLContext
。
有关更多详细信息,请参阅 JooqAutoConfiguration
。
特别是,JooqExceptionTranslator 和SpringTransactionProvider 可以重用,以提供与自动配置对单个DataSource 所做的类似的功能。 |