Springboot核心知識(shí)點(diǎn)之?dāng)?shù)據(jù)訪問(wèn)配置
環(huán)境:Springboot2.4.13
自定義數(shù)據(jù)源配置
- @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類具有相應(yīng)的url,username,pool-size屬性。
Spring Boot還提供了一個(gè)名為DataSourceBuilder的實(shí)用工具生成器類,可用于創(chuàng)建一個(gè)標(biāo)準(zhǔn)數(shù)據(jù)源(如果它位于類路徑上)。構(gòu)建器可以根據(jù)類路徑上的可用內(nèi)容檢測(cè)要使用的類。它還根據(jù)JDBCURL自動(dòng)檢測(cè)驅(qū)動(dòng)程序。
- @Bean
 - @ConfigurationProperties("app.datasource")
 - public DataSource dataSource() {
 - return DataSourceBuilder.create().build();
 - }
 
然而,有一個(gè)陷阱。因?yàn)檫B接池的實(shí)際類型沒(méi)有提供,所以在自定義數(shù)據(jù)源的元數(shù)據(jù)中沒(méi)有生成任何鍵,并且IDE中沒(méi)有可用的完成(因?yàn)閿?shù)據(jù)源接口不公開(kāi)任何屬性)。此外,如果類路徑上碰巧有Hikari,則此基本設(shè)置不起作用,因?yàn)镠ikari沒(méi)有url屬性(但有jdbcUrl屬性)。在這種情況下,你必須按如下方式重寫配置:
- app:
 - datasource:
 - jdbc-url: "jdbc:mysql://localhost/test"
 - username: "dbuser"
 - password: "dbpass"
 - pool-size: 30
 
可以強(qiáng)制指定數(shù)據(jù)源類型
- @Bean
 - @ConfigurationProperties("app.datasource")
 - public HikariDataSource dataSource() {
 - return DataSourceBuilder.create().type(HikariDataSource.class).build();
 - }
 
多數(shù)據(jù)源配置
如果需要配置多個(gè)數(shù)據(jù)源,可以應(yīng)用上一節(jié)中描述的相同技巧。但是,你必須將其中一個(gè)數(shù)據(jù)源實(shí)例標(biāo)記為@Primary,因?yàn)閷?lái)的各種自動(dòng)配置都希望能夠按類型獲得一個(gè)。
如果您創(chuàng)建自己的數(shù)據(jù)源,自動(dòng)配置將退出。在以下示例中,我們提供了與主數(shù)據(jù)源上的自動(dòng)配置完全相同的功能集:
- @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();
 - }
 
這兩個(gè)數(shù)據(jù)源還綁定了高級(jí)定制。例如,您可以按如下方式配置它們:
- 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
 
你也可以將相同的概念應(yīng)用于輔助數(shù)據(jù)源,如以下示例所示:
- @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 可以創(chuàng)建各種風(fēng)格的@Repository接口的實(shí)現(xiàn)。只要這些@Repositories包含在@EnableAutoConfiguration類的同一個(gè)包(或子包)中,Spring Boot就可以為您處理所有這些。
對(duì)于許多應(yīng)用程序,只需將正確的Spring Data依賴項(xiàng)放在類路徑上。
spring-boot-starter-data-jpa for JPA, spring-boot-starter-data-mongodb for Mongodb,等等。要開(kāi)始,請(qǐng)創(chuàng)建一些存儲(chǔ)庫(kù)接口來(lái)處理@Entity對(duì)象。
Spring Boot根據(jù)找到的@EnableAutoConfiguration,嘗試猜測(cè)@Repository定義的位置。要獲得更多控制,請(qǐng)使用@EnableJpaRepositories注釋。
將@Entity定義與Spring配置分開(kāi)
Spring Boot試圖根據(jù)它找到的@EnableAutoConfiguration猜測(cè)@Entity定義的位置。要獲得更多控制,可以使用@EntityScan注釋,如下例所示:
- @Configuration(proxyBeanMethods = false)
 - @EnableAutoConfiguration
 - @EntityScan(basePackageClasses=City.class)
 - public class Application {
 - //...
 - }
 
配置JPA屬性
Spring Data JPA已經(jīng)提供了一些獨(dú)立于供應(yīng)商的配置選項(xiàng)(如SQL日志記錄選項(xiàng)),SpringBoot將這些選項(xiàng)和Hibernate的一些選項(xiàng)公開(kāi)為外部配置屬性。其中一些是根據(jù)上下文自動(dòng)檢測(cè)的,因此您不必設(shè)置它們。
spring.jpa.hibernate.ddl-auto是一種特殊情況,因?yàn)楦鶕?jù)運(yùn)行時(shí)條件,它有不同的默認(rèn)值。如果使用嵌入式數(shù)據(jù)庫(kù),并且沒(méi)有模式管理器(如Liquibase或Flyway)處理數(shù)據(jù)源,則默認(rèn)情況下為create-drop。在所有其他情況下,它默認(rèn)為none。
要使用的方言由JPA提供程序檢測(cè)。如果您喜歡自己設(shè)置方言,請(qǐng)?jiān)O(shè)置
spring.jpa.database-platform屬性。
- spring:
 - jpa:
 - hibernate:
 - naming:
 - physical-strategy: "com.example.MyPhysicalNamingStrategy"
 - show-sql: true
 
配置Hibernate命名策略
Hibernate使用兩種不同的命名策略將名稱從對(duì)象模型映射到相應(yīng)的數(shù)據(jù)庫(kù)名稱??梢酝ㄟ^(guò)設(shè)置
spring.jpa.hibernate.naming.physical-strategy屬性,屬性值為類的全限定名,package + clalss。
默認(rèn)情況下,Spring Boot使用
SpringPhysicalNamingStrategy配置物理命名策略。此實(shí)現(xiàn)提供了與Hibernate4相同的表結(jié)構(gòu):所有點(diǎn)都替換為下劃線,駝峰大小寫也替換為下劃線。此外,默認(rèn)情況下,所有表名都以小寫形式生成。例如,電話號(hào)碼實(shí)體映射到電話號(hào)碼表。如果您的模式需要混合大小寫標(biāo)識(shí)符,請(qǐng)定義自定義SpringPhysicalNamingStrategybean,如以下示例所示:
- @Bean
 - SpringPhysicalNamingStrategy caseSensitivePhysicalNamingStrategy() {
 - return new SpringPhysicalNamingStrategy() {
 - @Override
 - protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) {
 - return false;
 - }
 - };
 - }
 
如果您更喜歡使用Hibernate 5的默認(rèn)設(shè)置,請(qǐng)?jiān)O(shè)置以下屬性:
- spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
 
或者,您可以配置以下bean
- @Bean
 - public PhysicalNamingStrategy physicalNamingStrategy() {
 - return new PhysicalNamingStrategyStandardImpl();
 - }
 
配置Hibernat二級(jí)緩存
Hibernate二級(jí)緩存可以為一系列緩存提供程序進(jìn)行配置。與其將Hibernate配置為再次查找緩存提供程序,不如盡可能提供上下文中可用的緩存提供程序。
要使用JCache實(shí)現(xiàn)這一點(diǎn),首先要確保
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());
 - }
 - }
 
使用多個(gè)EntityManagerFactories
如果需要對(duì)多個(gè)數(shù)據(jù)源使用JPA,那么每個(gè)數(shù)據(jù)源可能需要一個(gè)EntityManagerFactory。Spring ORM中的
LocalContainerEntityManagerFactoryBean允許您根據(jù)需要配置EntityManagerFactory。您還可以重用JPA屬性來(lái)綁定每個(gè)EntityManagerFactory的設(shè)置,如以下示例所示:
- @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的數(shù)據(jù)源bean創(chuàng)建EntityManagerFactory。它掃描與訂單位于同一包中的實(shí)體。可以使用該應(yīng)用程序映射其他JPA屬性。
將Spring數(shù)據(jù)存儲(chǔ)庫(kù)公開(kāi)為REST端點(diǎn)
Spring Data Rest可以將 Repository 實(shí)現(xiàn)公開(kāi)為REST端點(diǎn),前提是已經(jīng)為應(yīng)用程序啟用了 SpringMVC。
Spring Boot暴露了一組有用的屬性(來(lái)自Spring.data.rest命名空間),用于自定義
RepositoryRestConfiguration。如果需要提供額外的定制,那么應(yīng)該使用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>
 















 
 
 














 
 
 
 