整合JDBC與數據源自動配置原理

(一)整合連接

SpringBoot依賴啓動選擇:
1:web-SpringWeb
2:SQL: JDBC、MySQL

參考依賴

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
  </dependency>

application.yml配置文件設置

spring:
  datasource:
    username: root
    password: admin
    url: jdbc:mysql://127.0.0.1:3306/test
    driver‐class‐name: com.mysql.jdbc.Driver

測試連接

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootJdbcApplicationTests {

    //注入數據源
    @Autowired
    DataSource  dataSource;


    @Test
    public void contextLoads() throws SQLException {
        System.out.println("------JDBC測試-------");
        System.out.println(dataSource.getConnection());

    }

}
(二)自動配置原理
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootJdbcApplicationTests {
    @Autowired
    DataSource dataSource;
    @Test
    public void contextLoads() throws SQLException {
        System.out.println("------JDBC測試-------");
        System.out.println("數據源類型:" + dataSource.getClass());
        System.out.println("數據源連接:" + dataSource.getConnection());
 }}

繼續上面的測試,本次將打印出數據源的類型,打印結果如下:

數據源類型:class org.apache.tomcat.jdbc.pool.DataSource

字面意思判斷,這個是tomcat關聯的數據源,那麼這個具體如何配置啓動的呢,根據SpringBoot自動配置原理,它的所有的自動配置都在org.springframework.boot.autoconfigure這個包下,因此我們如果想要了解更多去查找對應的自動配置即可,比如本次的jdbc

通過查找發現DataSourceConfiguration類中存在相應的數據源配置,通過觀察源碼可以發現其中包含了Tomcat數據源、Hikari數據源、DBCP數據源、dbcp2數據源、自定義數據源.

它們會根據提供的依賴來判斷並返回Bean,由於我們並沒有提供相關的依賴,但是SpringBoot默認是選擇tomcat容器相關組件的,因此在首次測試的DataSource的時候打印出的類型是tomcat數據源,所以如果想要切換需要添加相關的依賴

該類代碼的最後部分如下,描述的是創建自定義的數據源,它會根據提供的配置文件屬性建造一個自定義的數據源. 使用DataSourceBuilder創建數據源,利用反射創建響應type的數據源,並且綁定相關屬性。 比如c3p0數據源.

/**
	 * Generic DataSource configuration.
         表示的是根據配置自定義數據源
	 */
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type")
	static class Generic {
@Bean
		public DataSource dataSource(DataSourceProperties properties) {
			return properties.initializeDataSourceBuilder().build();
		}

	}
public DataSourceBuilder initializeDataSourceBuilder() {
		return DataSourceBuilder.create(getClassLoader()).type(getType())
				.driverClassName(determineDriverClassName()).url(determineUrl())
				.username(determineUsername()).password(determinePassword());
	}
(三)配置中數據源參考配置
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties
		implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {  ... }

配置文件中數據源的配置參考該類的成員屬性,前綴spring.datasource
其他配置詳見該類屬性字段

(四)自動配置腳本

在SpringBoot的架構中,DataSourceInitializer類可以實現自動執行腳本的功能。通過自定義DataSourceInitializer Bean就可以實現按照業務要求執行特定的腳本。

備註:自動配置腳本的前提是已經配置好了數據源,具體原因參考DataSourceInitializer方法中判斷

DML(Data Manipulation Language)數據操縱語言:

適用範圍:對數據庫中的數據進行一些簡單操作,如insert,delete,update,select等.

DDL(Data Definition Language)數據定義語言:
適用範圍:對數據庫中的某些對象(例如,database,table)進行管理,如Create,Alter和Drop.

使用方式一

通過觀察DataSourceInitializer類得出結論,該類作爲一個監聽器,當Servlet啓動時觸發事件,如果classpath路徑下有如下倆個SQL文件,那麼就事件就會去執行對應的腳本

schema.sql,schema‐all.sql;
使用方式二

除了限制上述倆個SQL文件名的方式外,還可以通過配置文件來執行其他名稱的SQL腳本
規則參考:schema‐.sql、data‐.sql .源碼參考如下

private void runDataScripts() {
		List<Resource> scripts = getScripts("spring.datasource.data",
				this.properties.getData(), "data");
		String username = this.properties.getDataUsername();
		String password = this.properties.getDataPassword();
		runScripts(scripts, username, password);
	}

	private List<Resource> getScripts(String propertyName, List<String> resources,
			String fallback) {
		if (resources != null) {
			return getResources(propertyName, resources, true);
		}
		String platform = this.properties.getPlatform();
		List<String> fallbackResources = new ArrayList<String>();
		fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");
		fallbackResources.add("classpath*:" + fallback + ".sql");
		return getResources(propertyName, fallbackResources, false);
	}

通過觀察可以發現其中data‐.sql針對的是DML操作,schema‐.sql針對的是DDL操作,代碼中的platform ,data變量是來自於DataSourceProperties成員屬性,我們知道該類是管理配置文件,因此我們可以通過配置文件來完成修改,但是需要以這樣的格式命名schema‐.sql、data‐.sql

spring:
  datasource:
    username: root
    password: admin
    url: jdbc:mysql://127.0.0.1:3306/test
    driver‐class‐name: com.mysql.jdbc.Driver
    platform: user

上述設置就能夠在啓動時識別資源路徑下的 schema-user.sql文件

使用方式三

通過屬性文件設置schema和data並且指定對應的路徑地址,可以含有多個執行語句

spring:
  datasource:
    username: root
    password: admin
    url: jdbc:mysql://127.0.0.1:3306/test
    driver‐class‐name: com.mysql.jdbc.Driver
    schema:
      - classpath:user1.sql
      - classpath:user2.sql
data: classpath:mysql.sql

注意:
1:classpath:user1.sql是一個整體字符串,不是屬性鍵值,沒有空格,否則報錯
2:對於自動加載SQL文件,必須有schema文件,才能執行data文件,參考代碼如下,所以,如果沒有對應的DDL語句,可以設置一個空的schema文件也可以,但是不能沒有schema而只存在data文件

if (!this.initialized) {
	runDataScripts();
	this.initialized = true;
}
(五)JdbcTemplate自動配置原理和使用

JdbcTemplate是默認提供給開發人員使用的數據操作類,其中該類SpringBoot已經完成自動配置,加載到單例池容器中.
自動配置原理類:
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration

@Configuration
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnSingleCandidate(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class JdbcTemplateAutoConfiguration {

	private final DataSource dataSource;

	public JdbcTemplateAutoConfiguration(DataSource dataSource) {
		this.dataSource = dataSource;
	}

	@Bean
	@Primary
	@ConditionalOnMissingBean(JdbcOperations.class)
	public JdbcTemplate jdbcTemplate() {
		return new JdbcTemplate(this.dataSource);
	}

	@Bean
	@Primary
	@ConditionalOnMissingBean(NamedParameterJdbcOperations.class)
	public NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
		return new NamedParameterJdbcTemplate(this.dataSource);
	}

}

代碼中jdbcTemplate方法頭部注入了@Bean註解,該方法已經完成了數據源的配置和封裝操作,並且在項目啓動的時候已完成Bean加載,說明我們是可以直接在項目中使用這個類對象的,下面給出簡單的測試實例

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootJdbcApplicationTests {
 @Autowired
    JdbcTemplate jdbcTemplate;
   @Test
    public void testJdbcTemplate() throws SQLException {
        System.out.println("------JdbcTemplate-------");
        System.out.println("查詢");
        List<Map<String, Object>> list = jdbcTemplate.queryForList("select   * from  `type`");
        Map<String, Object> object = list.get(0);
        System.out.println(object);
    }
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章