数据访问
Spring Boot 包含多个用于数据源作的入门程序。 本节回答与此相关的问题。
配置自定义数据源
自定义配置数据来源,定义一个@Bean你配置中那种类型的。
Spring靴可以重复使用你的数据来源任何需要的都要,包括数据库初始化。
如果你需要外部化某些设置,可以绑定你的数据来源到环境(参见第三方配置)。
以下示例展示了如何在豆子中定义数据源:
-
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("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("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
假设SomeDataSource具有常规的 JavaBean 属性,包括 URL、用户名和池大小,这些设置在数据来源可以供其他组件使用。
Spring Boot 还提供了一个实用工具构建类,称为数据源构建器,可以用来创建标准数据源之一(如果它在类路径上)。
构建者可以根据类路径上可用的内容检测到该用哪个。
它还会根据JDBC的URL自动检测驱动。
以下示例展示了如何通过使用数据源构建器:
-
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()
}
}
用它运行一个应用数据来源你只需要连接信息。
还可以提供针对泳池的具体设置。
查看运行时将要使用的实现以获取更多细节。
以下示例展示了如何通过设置属性来定义 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
然而,该方法存在一个问题数据来源返回类型。
这样会隐藏连接池的实际类型,所以不会为自定义生成配置属性元数据数据来源而且你的IDE中没有自动补全功能。
解决这个问题时,可以用架构商的类型(类别)用来指定 的类型数据来源构建并更新方法的返回类型。
例如,以下内容展示了如何创建光数据源跟数据源构建器:
-
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()
}
}
不幸的是,这个基本设定行不通,因为光没有网址财产。
相反,它拥有一个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(数据源属性)该 将处理网址自JDBC-URL给你翻译。
你可以初始化一个数据源构建器从任意状态DataSourceProperties(数据源属性)使用其对象initializeDataSourceBuilder()方法。
你可以注射DataSourceProperties(数据源属性)不过,Spring Boot会自动生成的配置会被拆分spring.datasource.*和App.datasource.*.
为了避免这种情况,可以定义自定义DataSourceProperties(数据源属性)带有自定义配置属性前缀,如下示例所示:
-
Java
-
Kotlin
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.autoconfigure.DataSourceProperties;
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.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.autoconfigure.DataSourceProperties
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 默认为你做的,只不过池的类型在代码中指定,设置是App.Datasource.configuration.*性能。DataSourceProperties(数据源属性)照顾网址自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不会有任何影响。
如支持连接池中所述,数据源构建器支持多个不同的连接池。
要使用除 Hikari 以外的池,可以将其添加到类路径中,使用类型(类别)方法指定要使用的池类,并更新@Bean方法的返回类型以匹配。
这也会为你选择的具体连接池提供配置属性元数据。
Spring Boot 会暴露 Hikari 专属设置Spring.数据源.光.
这个例子使用了一个更通用的配置子命名空间(如示例)不支持多个数据源实现。 |
参见配置数据源和DataSourceAutoConfiguration更多详情请见班级。
配置两个数据源
| Spring Framework 参考文档对该功能有更详细的描述。 |
以允许额外的数据来源要注射到需要的地方,也要注释:@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()
}
}
消耗额外的数据来源,用相同的注注入点@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
-
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.autoconfigure.DataSourceProperties;
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.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.autoconfigure.DataSourceProperties
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.*属性根据所选实现提供高级设置。
使用 Spring 数据仓库
Spring Data 可以创建存储 库各种界面。
Spring Boot 可以帮你处理这些,只要这些存储 库实现包含在自动配置包中,通常是你主应用类的包(或子包),并标注为@SpringBootApplication或@EnableAutoConfiguration.
对于许多应用,你只需要在类路径上添加正确的 Spring Data 依赖。
有一个Spring-boot-starter-data-jpa对于JPA,Spring-boot-starter-data-mongodb用于Mongodb,以及其他各种支持技术的入门。
要开始,可以创建一些仓库接口来处理你的@Entity对象。
有关Spring Data的更多信息,请参见Spring Data项目页面。
将@Entity定义与Spring配置区分开
Spring靴决定了你的位置@Entity通过扫描自动配置包来定义。
为了更好地控制,可以使用@EntityScan注释,如下示例所示:
-
Java
-
Kotlin
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.persistence.autoconfigure.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.persistence.autoconfigure.EntityScan
import org.springframework.context.annotation.Configuration
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
@EntityScan(basePackageClasses = [City::class])
class MyApplication {
// ...
}
滤波扫描@Entity定义
可以过滤@Entity使用 a 的定义ManagedClassNameFilter豆。
这在只需考虑可用实体子集的测试中非常有用。
在以下示例中,只有来自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)在处理,数据来源,默认为创作-丢弃.
在其他情况下,默认为没有.
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
此外,所有spring.jpa.properties.*当本地EntityManagerFactory被创造出来。
|
你需要确保定义在以下 例如,如果你想配置 Hibernate 的批次大小,你必须使用 |
如果你需要对休眠属性应用高级自定义,可以考虑注册一个HibernatePropertiesCustomizer在创建EntityManagerFactory. 这优先于自动配置所应用的任何内容。 |
配置休眠命名策略
休眠通过两种不同的命名策略将对象模型的名称映射到对应的数据库名称。物理和隐式策略实现的全限定类名可以通过设置spring.jpa.hibernate.命名.physical-strategy和spring.jpa.hibernate.naming.implicit-strategy分别为性质。或者,如果隐式命名策略或物理命名策略Beans 在应用环境中可以使用,Hibernate 会自动配置使用它们。
默认情况下,Spring Boot 配置物理命名策略为骆驼案 强调命名策略. 采用此策略,所有点被下划线替换,骆驼壳也被下划线替代。此外,默认情况下,所有表名均以小写字母生成。例如,a电话号码实体映射到telephone_number桌子。 如果你的模式需要混合大小写标识符,请自定义骆驼案 强调命名策略豆子,如下例所示:
-
Java
-
Kotlin
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategySnakeCaseImpl;
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 PhysicalNamingStrategySnakeCaseImpl caseSensitivePhysicalNamingStrategy() {
return new PhysicalNamingStrategySnakeCaseImpl() {
@Override
public Identifier toPhysicalColumnName(Identifier logicalName, JdbcEnvironment jdbcEnvironment) {
return logicalName;
}
};
}
}
import org.hibernate.boot.model.naming.Identifier
import org.hibernate.boot.model.naming.PhysicalNamingStrategySnakeCaseImpl
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(): PhysicalNamingStrategySnakeCaseImpl {
return object : PhysicalNamingStrategySnakeCaseImpl() {
override fun toPhysicalColumnName(logicalName: Identifier, jdbcEnvironment: JdbcEnvironment): Identifier {
return logicalName
}
}
}
}
如果你更倾向于使用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
或者,你也可以配置以下的豆子:
-
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()
}
}
配置休眠二级缓存
休眠二级缓存可以配置为多种缓存提供者。与其配置休眠重新查找缓存提供者,不如尽可能提供上下文中可用的缓存提供者。
要用 JCache 实现这一点,首先要确保org.hibernate.orm:hibernate-jcache在类路径中可用。然后,添加一个HibernatePropertiesCustomizer豆子,如下例所示:
-
Java
-
Kotlin
import org.hibernate.cache.jcache.ConfigSettings;
import org.springframework.boot.hibernate.autoconfigure.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.hibernate.autoconfigure.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 ->
val cacheManager = cacheManager.cacheManager
if (cacheManager != null) {
properties[ConfigSettings.CACHE_MANAGER] = cacheManager
}
}
}
}
在休眠组件中使用依赖注入
你可以通过注册 a 来禁用或调整这种行为HibernatePropertiesCustomizer这会移除或改变休眠资源Beans容器财产。
使用自定义的EntityManagerFactory
要完全控制EntityManagerFactory,你需要添加一个@Bean名为“entityManagerFactory”。Spring Boot 在遇到该类型的 bean 时会自动关闭其实体管理器。
当你为 创建豆子时LocalContainerEntityManagerFactoryBean你自己,以及在创建自动配置过程中应用的任何自定义LocalContainerEntityManagerFactoryBean丢失了。一定要用自动配置实体管理器工厂建设者以保留JPA和提供商的财产。如果你依赖Spring.jpa.*用于配置命名策略或DDL模式等属性。 |
使用 EntityManagerFactories
如果你需要对多个数据源使用JPA,通常需要一个EntityManagerFactory根据数据来源。 这LocalContainerEntityManagerFactoryBeanFrom Spring ORM 允许你配置EntityManagerFactory满足你的需求。你也可以重复使用JpaProperties(日本地产)绑定设置一秒钟EntityManagerFactory. 基于配置第二个的例子 数据来源,一秒钟EntityManagerFactory可以定义为如下示例所示:
-
Java
-
Kotlin
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.jpa.autoconfigure.JpaProperties;
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);
Function<DataSource, Map<String, ?>> jpaPropertiesFactory = (dataSource) -> createJpaProperties(dataSource,
jpaProperties.getProperties());
return new EntityManagerFactoryBuilder(jpaVendorAdapter, jpaPropertiesFactory, null);
}
private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
// ... map JPA properties as needed
return new HibernateJpaVendorAdapter();
}
private Map<String, ?> createJpaProperties(DataSource dataSource, Map<String, ?> existingProperties) {
Map<String, ?> jpaProperties = new LinkedHashMap<>(existingProperties);
// ... map JPA properties that require the DataSource (e.g. DDL flags)
return jpaProperties;
}
}
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jpa.EntityManagerFactoryBuilder
import org.springframework.boot.jpa.autoconfigure.JpaProperties
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
import javax.sql.DataSource
@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)
val jpaPropertiesFactory = { dataSource: DataSource ->
createJpaProperties(dataSource, jpaProperties.properties) }
return EntityManagerFactoryBuilder(jpaVendorAdapter, jpaPropertiesFactory, null)
}
private fun createJpaVendorAdapter(jpaProperties: JpaProperties): JpaVendorAdapter {
// ... map JPA properties as needed
return HibernateJpaVendorAdapter()
}
private fun createJpaProperties(dataSource: DataSource, existingProperties: Map<String, *>): Map<String, *> {
val jpaProperties: Map<String, *> = LinkedHashMap(existingProperties)
// ... map JPA properties that require the DataSource (e.g. DDL flags)
return jpaProperties
}
}
上述示例可生成EntityManagerFactory使用数据来源宾晋级为@Qualifier(“第二”). 它扫描位于同一包中的实体次序. 还可以利用App.JPANamespace。 的使用@Bean(defaultCandidate=false)允许第二Jpa属性和第二实体管理者工厂这些豆子需要定义,但不干扰同类型的自动配置豆子。
| Spring Framework 参考文档对该功能有更详细的描述。 |
你也应该为需要JPA访问权限的其他数据源提供类似配置。
为了完成整个情况,你需要配置一个JpaTransactionManager每个EntityManagerFactory也。
或者,你也可以使用跨越两者的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 = "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 不会搜索或使用元步兵/persistence.xml默认。
如果你更喜欢用传统persistence.xml你需要自己定义@Bean类型LocalEntityManagerFactoryBean(ID 为 'entityManagerFactory')并在那里设置了持久化单元名称。
看JpaBaseConfiguration对于默认设置。
使用Spring Data JPA和Mongo仓库
Spring Data JPA 和 Spring Data Mongo 都能自动创建存储 库为你准备实现。
如果它们都存在于类路径上,您可能需要额外配置,告诉 Spring Boot 要创建哪些仓库。
最明确的方法是使用标准的Spring数据@EnableJpaRepositories和@EnableMongoRepositories注释并提供您的位置存储 库接口。
还有旗帜(spring.data.*.repositories.enabled和spring.data.*.repositories.type你可以用它来在外部配置中开关自动配置的仓库。
这样做很有用,比如你想关闭Mongo仓库,但仍然使用自动配置Mongo模板.
其他自动配置的 Spring Data 仓库类型(如 Elasticsearch、Redis 等)也存在同样的障碍和功能。 要与它们合作,可以相应地更改注释和标记的名称。
自定义Spring Data的网页支持
Spring Data 提供网页支持,简化了在 Web 应用中使用 Spring Data 仓库。
Spring Boot 提供以下属性spring.data.web用于自定义配置的命名空间。
注意,如果你使用了 Spring Data REST,必须使用以下属性spring.data.rest改为命名空间。
Expose Spring Data Repositories as REST Endpoint
Spring Data REST 可以公开存储 库作为 REST 端点的实现,为你提供,
前提是该应用启用了 Spring MVC。
Spring Boot 揭示了一组有用的属性(来自spring.data.rest命名空间)中可以自定义RepositoryRestConfiguration.
如果你需要额外的定制,应该使用RepositoryRestConfigurer豆。
如果你在自定义中没有指定任何订单RepositoryRestConfigurer它运行于Spring Boot内部使用的程序之后。
如果你需要指定订单,确保它大于0。 |
配置JPA使用的组件
如果你想配置JPA使用的组件,那么你需要确保组件在JPA之前被初始化。 当组件自动配置时,Spring Boot 会帮你处理这些。 例如,当 Flyway 被自动配置时,Hibernate 被配置为依赖 Flyway,这样 Flyway 有机会在 Hibernate 尝试使用之前初始化数据库。
如果你自己配置组件,可以使用EntityManagerFactoryDependsOnPostProcessor子类作为设置必要依赖关系的便捷方式。
例如,如果你使用休眠搜索并使用 Elasticsearch 作为索引管理器,任何EntityManagerFactory豆子必须配置为依赖于elasticsearch客户端豆子,如下例所示:
-
Java
-
Kotlin
import jakarta.persistence.EntityManagerFactory;
import org.springframework.boot.jpa.autoconfigure.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.jpa.autoconfigure.EntityManagerFactoryDependsOnPostProcessor
import org.springframework.stereotype.Component
@Component
class ElasticsearchEntityManagerFactoryDependsOnPostProcessor :
EntityManagerFactoryDependsOnPostProcessor("elasticsearchClient")
配置 jOOQ 使用两个数据源
如果你需要在多个数据源中使用 jOOQ,你应该自己创建一个DSLContext每一个。
看JooqAutoConfiguration更多细节请阅读。
特别ExceptionTranslatorExecuteListener和SpringTransactionProvider可以重复使用,以提供类似于自动配置对单个配置的功能数据来源. |