数据访问

Spring Boot 包括许多用于处理数据源的Starters。 本节回答与执行此作相关的问题。spring-doc.cadn.net.cn

配置自定义数据源

配置您自己的DataSource,定义一个@Bean配置中的该类型。 Spring Boot 重用了DataSource任何需要的地方,包括数据库初始化。 如果需要外部化某些设置,可以绑定DataSource到环境(请参阅第三方配置)。spring-doc.cadn.net.cn

以下示例显示了如何在 Bean 中定义数据源:spring-doc.cadn.net.cn

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()
	}

}

以下示例演示如何通过设置数据源的属性来定义数据源:spring-doc.cadn.net.cn

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-doc.cadn.net.cn

Spring Boot 还提供了一个实用程序构建器类,称为DataSourceBuilder,可用于创建标准数据源之一(如果它在类路径上)。 构建器可以根据类路径上可用的内容来检测要使用哪一个。 它还会根据 JDBC URL 自动检测驱动程序。spring-doc.cadn.net.cn

以下示例演示如何使用DataSourceBuilder:spring-doc.cadn.net.cn

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,您所需要的只是连接信息。 还可以提供特定于池的设置。 检查将在运行时使用的实现以了解更多详细信息。spring-doc.cadn.net.cn

以下示例显示了如何通过设置属性来定义 JDBC 数据源:spring-doc.cadn.net.cn

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 中没有可用的自动完成功能。 要解决此问题,请使用构建器的type(Class)指定类型的方法DataSource以生成并更新方法的返回类型。 例如,下面演示了如何创建HikariDataSourceDataSourceBuilder:spring-doc.cadn.net.cn

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属性,这意味着您必须按如下方式重写配置:spring-doc.cadn.net.cn

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这将处理urljdbc-url为您翻译。 您可以初始化一个DataSourceBuilder从任何状态DataSourceProperties对象使用其initializeDataSourceBuilder()方法。 您可以注入DataSourceProperties但是,Spring Boot 会自动创建,这将拆分您的配置spring.datasource.*app.datasource.*. 为避免这种情况,请定义自定义DataSourceProperties使用自定义配置属性前缀,如以下示例所示:spring-doc.cadn.net.cn

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 默认为您执行的作,只是池的类型在代码中指定,并且其设置公开为app.datasource.configuration.*性能。DataSourceProperties照顾urljdbc-urltranslation,因此您可以按如下方式配置它:spring-doc.cadn.net.cn

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不会有任何效果。spring-doc.cadn.net.cn

支持的连接池中所述,DataSourceBuilder支持多个不同的连接池。 要使用 Hikari 以外的池,请将其添加到类路径中,使用type(Class)方法来指定要使用的池类,并更新@Bean方法的返回类型。 这还将为所选的特定连接池提供配置属性元数据。spring-doc.cadn.net.cn

Spring Boot 将 Hikari 特定设置公开给spring.datasource.hikari. 此示例使用更通用的configurationsub 命名空间,因为示例不支持多个数据源实现。

配置两个数据源

要定义附加DataSource,可以使用与上一节类似的方法。 一个关键的区别是DataSource @Bean必须使用defaultCandidate=false. 这可以防止自动配置的DataSource从退缩。spring-doc.cadn.net.cn

Spring Framework 参考文档更详细地描述了此功能。

要允许额外的DataSource要注入到需要的地方,还要用@Qualifier如以下示例所示:spring-doc.cadn.net.cn

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.spring-doc.cadn.net.cn

自动配置的数据源和其他数据源可以按如下方式配置:spring-doc.cadn.net.cn

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可通过spring.datasource.configuration.*性能。 您可以将相同的概念应用于附加的DataSource同样,如以下示例所示:spring-doc.cadn.net.cn

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.*属性根据所选实现提供高级设置。spring-doc.cadn.net.cn

配置单个自定义一样DataSource,其中一个或两个DataSource可以使用type(Class)方法DataSourceBuilder. 有关支持的类型的详细信息,请参阅支持的连接池spring-doc.cadn.net.cn

使用 Spring Data Repositories

Spring Data 可以创建Repository各种口味的界面。 Spring Boot 会为您处理所有这些,只要这些Repository实现包含在其中一个自动配置包中,通常是主应用程序类的包(或子包),该类的注释为@SpringBootApplication@EnableAutoConfiguration.spring-doc.cadn.net.cn

对于许多应用程序,您所需要做的就是在类路径上放置正确的 Spring Data 依赖项。 有一个spring-boot-starter-data-jpa对于 JPA,spring-boot-starter-data-mongodb用于 Mongodb,以及支持技术的其他各种Starters。 首先,请创建一些存储库接口来处理@Entity对象。spring-doc.cadn.net.cn

Spring Boot 确定您的Repository通过扫描自动配置包来实现。 要获得更多控制,请使用@Enable…Repositories来自 Spring Data 的注释。spring-doc.cadn.net.cn

有关 Spring Data 的更多信息,请参阅 Spring Data 项目页面spring-doc.cadn.net.cn

将@Entity定义与 Spring 配置分开

Spring Boot 确定您的@Entity通过扫描自动配置包来定义。 要获得更多控制,请使用@EntityScan注释,如以下示例所示:spring-doc.cadn.net.cn

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定义

可以过滤@Entity使用ManagedClassNameFilter豆。 当仅考虑可用实体的子集时,这在测试中很有用。 在以下示例中,只有来自com.example.app.customer套餐包括:spring-doc.cadn.net.cn

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-doc.cadn.net.cn

spring.jpa.hibernate.ddl-auto是一种特殊情况,因为根据运行时条件,它具有不同的默认值。 如果使用嵌入式数据库,并且没有模式管理器(例如 Liquibase 或 Flyway)处理DataSource,则默认为create-drop. 在所有其他情况下,它默认为none.spring-doc.cadn.net.cn

JPA 提供程序检测到要使用的方言。 如果您更喜欢自己设置方言,请将spring.jpa.database-platform财产。spring-doc.cadn.net.cn

以下示例显示了最常见的设置选项:spring-doc.cadn.net.cn

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被创建。spring-doc.cadn.net.cn

您需要确保在spring.jpa.properties.*完全符合您的 JPA 提供者的预期。 Spring Boot 不会尝试对这些条目进行任何类型的宽松绑定。spring-doc.cadn.net.cn

例如,如果要配置 Hibernate 的批量大小,则必须使用spring.jpa.properties.hibernate.jdbc.batch_size. 如果您使用其他表单,例如batchSizebatch-size,Hibernate 将不会应用该设置。spring-doc.cadn.net.cn

如果您需要对 Hibernate 属性应用高级自定义,请考虑注册一个HibernatePropertiesCustomizerbean,该 bean 将在创建EntityManagerFactory. 这优先于自动配置应用的任何内容。

配置 Hibernate 命名策略

Hibernate 使用两种不同的命名策略将对象模型中的名称映射到相应的数据库名称。 物理和隐式策略实现的完全限定类名可以通过设置spring.jpa.hibernate.naming.physical-strategyspring.jpa.hibernate.naming.implicit-strategy属性。 或者,如果ImplicitNamingStrategyPhysicalNamingStrategybean 在应用程序上下文中可用,Hibernate 将自动配置为使用它们。spring-doc.cadn.net.cn

默认情况下,Spring Boot 使用CamelCaseToUnderscoresNamingStrategy. 使用此策略,所有点都替换为下划线,驼峰大小写也替换为下划线。 此外,默认情况下,所有表名都以小写形式生成。 例如,一个TelephoneNumber实体映射到telephone_number桌子。 如果您的架构需要混合大小写标识符,请定义自定义CamelCaseToUnderscoresNamingStrategybean,如以下示例所示:spring-doc.cadn.net.cn

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 的默认值,请设置以下属性:spring-doc.cadn.net.cn

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:spring-doc.cadn.net.cn

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()
	}

}

配置休眠二级缓存

可以为一系列缓存提供程序配置 Hibernate 二级缓存。 与其将 Hibernate 配置为再次查找缓存提供者,不如尽可能提供上下文中可用的缓存提供者。spring-doc.cadn.net.cn

要使用 JCache 执行此作,请首先确保org.hibernate.orm:hibernate-jcache在类路径上可用。 然后,添加一个HibernatePropertiesCustomizerbean,如以下示例所示:spring-doc.cadn.net.cn

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 用户指南spring-doc.cadn.net.cn

在 Hibernate 组件中使用依赖注入

默认情况下,Spring Boot 注册一个BeanContainer使用BeanFactory以便转换器和实体侦听器可以使用定期依赖注入。spring-doc.cadn.net.cn

您可以通过注册HibernatePropertiesCustomizer删除或更改hibernate.resource.beans.container财产。spring-doc.cadn.net.cn

使用自定义 EntityManagerFactory

要完全控制EntityManagerFactory,您需要添加一个@Bean名为“entityManagerFactory”。 Spring Boot 自动配置在存在该类型的 bean 时关闭其实体管理器。spring-doc.cadn.net.cn

当您为LocalContainerEntityManagerFactoryBean您自己,在创建自动配置期间应用的任何自定义LocalContainerEntityManagerFactoryBean丢失了。 确保使用自动配置的EntityManagerFactoryBuilder以保留 JPA 和提供商属性。 如果您依赖spring.jpa.*用于配置命名策略或 DDL 模式等内容的属性。

使用多个 EntityManagerFactories

如果您需要对多个数据源使用 JPA,那么您可能需要一个EntityManagerFactory每个数据源。 这LocalContainerEntityManagerFactoryBeanfrom Spring ORM 允许您配置EntityManagerFactory满足您的需求。 您还可以重复使用JpaProperties绑定设置一秒钟EntityManagerFactory. 基于配置第二个 DataSource,秒EntityManagerFactory可以定义,如以下示例所示:spring-doc.cadn.net.cn

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.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);
		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.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
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使用DataSourcebean 符合@Qualifier("second"). 它扫描位于与Order. 可以使用app.jpaNamespace。 使用@Bean(defaultCandidate=false)允许secondJpaPropertiessecondEntityManagerFactory在不干扰相同类型的自动配置 bean 的情况下定义 bean。spring-doc.cadn.net.cn

Spring Framework 参考文档更详细地描述了此功能。

您应该为需要 JPA 访问权限的任何其他数据源提供类似的配置。 要完成图片,您需要配置一个JpaTransactionManager对于每个EntityManagerFactory也。 或者,您可以使用跨两者的 JTA 事务管理器。spring-doc.cadn.net.cn

如果使用 Spring Data,则需要配置@EnableJpaRepositories因此,如以下示例所示:spring-doc.cadn.net.cn

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
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,您需要定义自己的@Bean类型LocalEntityManagerFactoryBean(ID 为 'entityManagerFactory') 并在其中设置持久性单元名称。spring-doc.cadn.net.cn

使用 Spring Data JPA 和 Mongo 存储库

Spring Data JPA 和 Spring Data Mongo 都可以自动创建Repository为您实现。 如果它们都存在于类路径上,则可能需要执行一些额外的配置来告诉 Spring Boot 要创建哪些存储库。 最明确的方法是使用标准的 Spring Data@EnableJpaRepositories@EnableMongoRepositories注释并提供您的位置Repository接口。spring-doc.cadn.net.cn

还有标志(spring.data.*.repositories.enabledspring.data.*.repositories.type),可用于在外部配置中打开和关闭自动配置的存储库。 这样做很有用,例如,如果您想关闭 Mongo 存储库并仍然使用自动配置的MongoTemplate.spring-doc.cadn.net.cn

其他自动配置的 Spring Data 存储库类型(Elasticsearch、Redis 等)也存在相同的障碍和相同的功能。 要使用它们,请相应地更改注释和标志的名称。spring-doc.cadn.net.cn

自定义 Spring Data 的 Web 支持

Spring Data 提供 Web 支持,可简化 Web 应用程序中 Spring Data 存储库的使用。 Spring Boot 在spring.data.web命名空间,用于自定义其配置。 请注意,如果您使用的是 Spring Data REST,则必须使用spring.data.rest命名空间。spring-doc.cadn.net.cn

将 Spring 数据存储库公开为 REST 端点

Spring Data REST 可以公开Repository实现作为 REST 端点, 前提是已为应用程序启用了 Spring MVC。spring-doc.cadn.net.cn

Spring Boot 公开了一组有用的属性(从spring.data.rest命名空间),自定义RepositoryRestConfiguration. 如果需要提供额外的自定义,则应使用RepositoryRestConfigurer豆。spring-doc.cadn.net.cn

如果您未在自定义中指定任何订单RepositoryRestConfigurer,它运行在 Spring Boot 内部使用的那个之后。 如果您需要指定订单,请确保它大于 0。

配置 JPA 使用的组件

如果要配置 JPA 使用的组件,那么需要确保该组件在 JPA 之前初始化。 当组件自动配置时,Spring Boot 会为您处理此问题。 例如,当 Flyway 自动配置时,Hibernate 被配置为依赖于 Flyway,以便 Flyway 有机会在 Hibernate 尝试使用它之前初始化数据库。spring-doc.cadn.net.cn

如果您自己配置组件,则可以使用EntityManagerFactoryDependsOnPostProcessor子类作为设置必要依赖项的便捷方式。 例如,如果您使用 Hibernate Search 和 Elasticsearch 作为其索引管理器,则任何EntityManagerFactorybean 必须配置为依赖于elasticsearchClientbean,如以下示例所示:spring-doc.cadn.net.cn

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了解更多详情。spring-doc.cadn.net.cn

特别ExceptionTranslatorExecuteListenerSpringTransactionProvider可以重复使用,以提供与自动配置对单个DataSource.