深入了解Springboot核心知识点之数据访问配置
环境:Springboot2.4.13
自定义数据源配置
@Bean @ConfigurationProperties(prefix="app.datasource") public DataSource dataSource() { return new FancyDataSource(); }
配置文件
app: datasource: url: "jdbc:h2:mem:mydb" username: "sa" password: "123123" pool-size: 30
FancyDataSource类具有相应的url,username,pool-size属性。
Spring Boot还提供了一个名为DataSourceBuilder的实用工具生成器类,可用于创建一个标准数据源(如果它位于类路径上)。构建器可以根据类路径上的可用内容检测要使用的类。它还根据JDBCURL自动检测驱动程序。
@Bean @ConfigurationProperties("app.datasource") public DataSource dataSource() { return DataSourceBuilder.create().build(); }
然而,有一个陷阱。因为连接池的实际类型没有提供,所以在自定义数据源的元数据中没有生成任何键,并且IDE中没有可用的完成(因为数据源接口不公开任何属性)。此外,如果类路径上碰巧有Hikari,则此基本设置不起作用,因为Hikari没有url属性(但有jdbcUrl属性)。在这种情况下,你必须按如下方式重写配置:
app: datasource: jdbc-url: "jdbc:mysql://localhost/test" username: "dbuser" password: "dbpass" pool-size: 30
可以强制指定数据源类型
@Bean @ConfigurationProperties("app.datasource") public HikariDataSource dataSource() { return DataSourceBuilder.create().type(HikariDataSource.class).build(); }
多数据源配置
如果需要配置多个数据源,可以应用上一节中描述的相同技巧。但是,你必须将其中一个数据源实例标记为@Primary,因为将来的各种自动配置都希望能够按类型获得一个。
如果您创建自己的数据源,自动配置将退出。在以下示例中,我们提供了与主数据源上的自动配置完全相同的功能集:
@Bean @Primary @ConfigurationProperties("app.datasource.first") public DataSourceProperties firstDataSourceProperties() { return new DataSourceProperties(); } @Bean @Primary @ConfigurationProperties("app.datasource.first.configuration") public HikariDataSource firstDataSource() { return firstDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build(); } @Bean @ConfigurationProperties("app.datasource.second") public BasicDataSource secondDataSource() { return DataSourceBuilder.create().type(BasicDataSource.class).build(); }
这两个数据源还绑定了高级定制。例如,您可以按如下方式配置它们:
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
你也可以将相同的概念应用于辅助数据源,如以下示例所示:
@Bean @Primary @ConfigurationProperties("app.datasource.first") public DataSourceProperties firstDataSourceProperties() { return new DataSourceProperties(); } @Bean @Primary @ConfigurationProperties("app.datasource.first.configuration") public HikariDataSource firstDataSource() { 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() { return secondDataSourceProperties().initializeDataSourceBuilder().type(BasicDataSource.class).build(); }
使用Spring Data Repositories
Spring data 可以创建各种风格的@Repository接口的实现。只要这些@Repositories包含在@EnableAutoConfiguration类的同一个包(或子包)中,Spring Boot就可以为您处理所有这些。
对于许多应用程序,只需将正确的Spring Data依赖项放在类路径上。
spring-boot-starter-data-jpa for JPA, spring-boot-starter-data-mongodb for Mongodb,等等。要开始,请创建一些存储库接口来处理@Entity对象。
Spring Boot根据找到的@EnableAutoConfiguration,尝试猜测@Repository定义的位置。要获得更多控制,请使用@EnableJpaRepositories注释。
将@Entity定义与Spring配置分开
Spring Boot试图根据它找到的@EnableAutoConfiguration猜测@Entity定义的位置。要获得更多控制,可以使用@EntityScan注释,如下例所示:
@Configuration(proxyBeanMethods = false) @EnableAutoConfiguration @EntityScan(basePackageClasses=City.class) public class Application { //... }
配置JPA属性
Spring Data JPA已经提供了一些独立于供应商的配置选项(如SQL日志记录选项),SpringBoot将这些选项和Hibernate的一些选项公开为外部配置属性。其中一些是根据上下文自动检测的,因此您不必设置它们。
spring.jpa.hibernate.ddl-auto是一种特殊情况,因为根据运行时条件,它有不同的默认值。如果使用嵌入式数据库,并且没有模式管理器(如Liquibase或Flyway)处理数据源,则默认情况下为create-drop。在所有其他情况下,它默认为none。
要使用的方言由JPA提供程序检测。如果您喜欢自己设置方言,请设置
spring.jpa.database-platform属性。
spring: jpa: hibernate: naming: physical-strategy: "com.example.MyPhysicalNamingStrategy" show-sql: true
配置Hibernate命名策略
Hibernate使用两种不同的命名策略将名称从对象模型映射到相应的数据库名称。可以通过设置
spring.jpa.hibernate.naming.physical-strategy属性,属性值为类的全限定名,package + clalss。
默认情况下,Spring Boot使用
SpringPhysicalNamingStrategy配置物理命名策略。此实现提供了与Hibernate4相同的表结构:所有点都替换为下划线,驼峰大小写也替换为下划线。此外,默认情况下,所有表名都以小写形式生成。例如,电话号码实体映射到电话号码表。如果您的模式需要混合大小写标识符,请定义自定义SpringPhysicalNamingStrategybean,如以下示例所示:
@Bean SpringPhysicalNamingStrategy caseSensitivePhysicalNamingStrategy() { return new SpringPhysicalNamingStrategy() { @Override protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) { return false; } }; }
如果您更喜欢使用Hibernate 5的默认设置,请设置以下属性:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
或者,您可以配置以下bean
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
配置Hibernat二级缓存
Hibernate二级缓存可以为一系列缓存提供程序进行配置。与其将Hibernate配置为再次查找缓存提供程序,不如尽可能提供上下文中可用的缓存提供程序。
要使用JCache实现这一点,首先要确保
org.hibernate.HibernateJCache在类路径上可用。然后,添加HibernatePropertiesCustomizer bean,如以下示例所示:
@Configuration(proxyBeanMethods = false) public class HibernateSecondLevelCacheExample { @Bean public HibernatePropertiesCustomizer hibernateSecondLevelCacheCustomizer(JCacheCacheManager cacheManager) { return (properties) -> properties.put(ConfigSettings.CACHE_MANAGER, cacheManager.getCacheManager()); } }
使用多个EntityManagerFactories
如果需要对多个数据源使用JPA,那么每个数据源可能需要一个EntityManagerFactory。Spring ORM中的
LocalContainerEntityManagerFactoryBean允许您根据需要配置EntityManagerFactory。您还可以重用JPA属性来绑定每个EntityManagerFactory的设置,如以下示例所示:
@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(); }
上面的示例使用名为firstDataSource的数据源bean创建EntityManagerFactory。它扫描与订单位于同一包中的实体。可以使用该应用程序映射其他JPA属性。
将Spring数据存储库公开为REST端点
Spring Data Rest可以将 Repository 实现公开为REST端点,前提是已经为应用程序启用了 SpringMVC。
Spring Boot暴露了一组有用的属性(来自Spring.data.rest命名空间),用于自定义
RepositoryRestConfiguration。如果需要提供额外的定制,那么应该使用RepositoryRestConfiguration。
使用
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-rest-webmvc</artifactId> </dependency>