SpringBoot使用編程方式配置DataSource

Spring Boot使用固定算法來掃描和配置DataSource。這使咱們能夠在默認狀況下輕鬆得到徹底配置的DataSource實現。html

Spring Boot還會按順序快速的自動配置鏈接池(HikariCP, Apache Tomcat或Commons DBCP),具體取決於路徑中的哪些類。java

雖然Spring Boot的DataSource自動配置在大多數狀況下運行良好,但有時咱們須要更高級別的控制,所以咱們必須設置本身的DataSource實現,所以忽略自動配置過程。算法

Maven依賴


整體而言,以編程方式建立DataSource實現很是簡單。spring

爲了學習如何實現這一目標,咱們將實現一個簡單的存儲庫層,它將對某些JPA實體執行CRUD操做。sql

咱們來看看咱們的演示項目的依賴項:數據庫

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>2.4.1</version> 
    <scope>runtime</scope> 
</dependency>
複製代碼

咱們將使用內存中的H2數據庫實例來運行存儲庫層。經過這樣作,咱們將可以測試以編程方式配置的DataSource,而無需執行昂貴的數據庫操做。編程

讓咱們確保在Maven Central上查看最新版本的spring-boot-starter-data-jpa。api

配置DataSource


若是咱們堅持使用Spring Boot的DataSource自動配置並以當前狀態運行咱們的項目,程序將按預期工做。oracle

**Spring Boot將爲咱們完成全部重型基礎設施管道。**這包括建立H2 DataSource實現,該實現將由HikariCP,Apache Tomcat或Commons DBCP自動處理,並設置內存數據庫實例。app

此外,咱們甚至不須要建立application.properties文件,由於Spring Boot也會提供一些默認的數據庫設置。

正如咱們以前提到的,有時咱們須要更高級別的自定義,所以咱們必須以編程方式配置咱們本身的DataSource實現。

實現此目的的最簡單方法是定義DataSource工廠方法,並將其放在使用@Configuration註解的類中:

@Configuration
public class DataSourceConfig {
     
    @Bean
    public DataSource getDataSource() {
        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
        dataSourceBuilder.driverClassName("org.h2.Driver");
        dataSourceBuilder.url("jdbc:h2:mem:test");
        dataSourceBuilder.username("SA");
        dataSourceBuilder.password("");
        return dataSourceBuilder.build();
    }
}
複製代碼

在這種狀況下,咱們使用方便的DataSourceBuilder類 - 一個簡潔的Joshua Bloch構建器模式 - 以編程方式建立咱們的自定義DataSource對象。

這種方法很是好,由於構建器可使用一些經常使用屬性輕鬆配置DataSource。此外,它還可使用底層鏈接池。

使用application.properties文件外部化DataSource配置


固然,也能夠部分外部化咱們的DataSource配置。例如,咱們能夠在工廠方法中定義一些基本的DataSource屬性:

@Bean
public DataSource getDataSource() { 
    DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); 
    dataSourceBuilder.username("SA"); 
    dataSourceBuilder.password(""); 
    return dataSourceBuilder.build(); 
}
複製代碼

並在application.properties文件中指定一些額外的配置:

spring.datasource.url=jdbc:h2:mem:test
spring.datasource.driver-class-name=org.h2.Driver
複製代碼

在外部源中定義的屬性(例如上面的application.properties文件或經過使用@ConfigurationProperties註解的類)將覆蓋Java API中定義的屬性。

很明顯,經過這種方法,咱們再也不將DataSource配置設置保存在一個地方。

另外一方面,它容許咱們保持編譯時和運行時配置彼此並很好地分離。

這很是好,由於它容許咱們輕鬆設置綁定點。這樣咱們能夠從其餘來源包含不一樣的DataSource,而無需重構咱們的bean工廠方法。

測試DataSource配置


測試咱們的自定義DataSource配置很是簡單。整個過程歸結爲建立JPA實體,定義基本存儲庫接口以及測試存儲庫層。

  • 建立JPA實體

讓咱們開始定義咱們的示例JPA實體類,它將爲用戶建模:

@Entity
@Table(name = "users")
public class User {
     
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String name;
    private String email;
 
    // standard constructors / setters / getters / toString
     
}
複製代碼
  • 存儲庫層

咱們須要實現一個基本的存儲庫層,它容許咱們對上面定義的User實體類的實例執行CRUD操做。

因爲咱們使用的是Spring Data JPA,所以咱們沒必要從頭開始建立本身的DAO實現。咱們只須要擴展CrudRepository接口得到一個工做的存儲庫實現:

@Repository
public interface UserRepository extends CrudRepository<User, Long> {}
複製代碼
  • 測試存儲庫層

最後,咱們須要檢查咱們的編程配置的DataSource是否實際工做。咱們能夠經過集成測試輕鬆完成此任務:

@RunWith(SpringRunner.class)
@DataJpaTest
public class UserRepositoryIntegrationTest {
     
    @Autowired
    private UserRepository userRepository;
    
    @Test
    public void whenCalledSave_thenCorrectNumberOfUsers() {
        userRepository.save(new User("Bob", "bob@domain.com"));
        List<User> users = (List<User>) userRepository.findAll();
         
        assertThat(users.size()).isEqualTo(1);
    }    
}
複製代碼

UserRepositoryIntegrationTest類是測試用例。它只是運行兩個存儲庫接口的CRUD方法來持久化並查找實體。

請注意,不管咱們是否決定以編程方式配置DataSource實現,或將其拆分爲Java配置方法和application.properties文件,咱們都應該始終得到有效的數據庫鏈接。

  • 運行示例應用程序

最後,咱們可使用標準的main()方法運行咱們的演示應用程序:

@SpringBootApplication
public class Application {
 
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
 
    @Bean
    public CommandLineRunner run(UserRepository userRepository) throws Exception {
        return (String[] args) -> {
            User user1 = new User("John", "john@domain.com");
            User user2 = new User("Julie", "julie@domain.com");
            userRepository.save(user1);
            userRepository.save(user2);
            userRepository.findAll().forEach(user -> System.out.println(user);
        };
    }
}
複製代碼

咱們已經測試了存儲庫層,所以咱們確信咱們的DataSource已經成功配置。所以,若是咱們運行示例應用程序,咱們應該在控制檯輸出中看到存儲在數據庫中的User實體列表。

相關文章
相關標籤/搜索