SpringBoot系列之JDBC數據訪問


SpringBoot系列之JDBC數據訪問

SpringBoot jdbc是比較常用的內容,本博客通過實驗並簡單跟源碼的方式進行介紹,希望可以幫助學習者更好地理解

環境准備:

  • IDEA
  • Maven

先新建一個項目:

New->Project or Module->Spring Initializer
在這里插入圖片描述
選擇JDBC和mysql驅動,為了方便測試web等等也可以選上
在這里插入圖片描述

項目創建成功之后,會自動配上如下的配置:

<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: root
    url: jdbc:mysql://127.0.0.1:3306/springboot
    driver-class-name: com.mysql.jdbc.Driver

新建一個junit測試類進行測試:

package com.example.springboot.jdbc;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

@SpringBootTest
class SppringbootJdbcApplicationTests {

	@Autowired
	DataSource dataSource;

	@Test
	public void contextLoads() throws SQLException {
		System.out.println(dataSource.getClass());
		Connection connection = dataSource.getConnection();
		System.out.println(connection);
		connection.close();
	}

}

啟動調試,發現控制台拋出異常信息:

Caused by: com.mysql.cj.exceptions.UnableToConnectException: CLIENT_PLUGIN_AUTH is required
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:85)
at com.mysql.cj.protocol.a.NativeAuthenticationProvider.connect(NativeAuthenticationProvider.java:205)
at com.mysql.cj.protocol.a.NativeProtocol.connect(NativeProtocol.java:1340)
at com.mysql.cj.NativeSession.connect(NativeSession.java:157)
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:956)
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:826)
... 90 more

原因是我的mysql服務器是5.+版本,而最新版2.2.1默認配置的mysql驅動版本是8.+的,8.+的驅動類是com.mysql.cj.jdbc.Driver,而非com.mysql.jdbc.Driver,所以解決方法還是手動加一下mysql驅動版本

<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.27</version>
			<scope>runtime</scope>
		</dependency>

ok,現在正常測試,測試通過:

class com.zaxxer.hikari.HikariDataSource
2019-12-14 15:47:25.241 INFO 6772 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-12-14 15:47:27.403 INFO 6772 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
HikariProxyConnection@23906266 wrapping com.mysql.jdbc.JDBC4Connection@717ed

可以看出2.2.1版本的Springboot默認數據源類是com.zaxxer.hikari.HikariDataSource,而1.+版本很多都是以org.apache.tomcat.jdbc.pool.DataSource為默認數據源類的,具體哪個版本開始改變的不清楚

既然Springboot默認使用hikari數據源,那就可以加上hikari的一些自定義配置

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf8&useSSL=true
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
    initialization-mode: always
    type: com.zaxxer.hikari.HikariDataSource

    hikari:
      jdbc-url: jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf8&useSSL=true
      minimum-idle: 5
      maximum-pool-size: 15
      auto-commit: true
      idle-timeout: 30000
      pool-name: DatebookHikariCP
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: select 1

經過調試,屬性配置是有起效的
在這里插入圖片描述
ok,掌握簡單應用之后,還是要跟一下源碼,依照經驗,找到對應的自動配置類DataSourceAutoConfiguration.java

不需要全部看懂源碼,只要找到關鍵的信息即可,如圖在這個自動配置類路其實就可以看出Springboot2.2.1支持的數據源種類有如下:
在這里插入圖片描述
點一下DataSourceConfiguration類,里面都是各種DataSource的配置,用了很多@Conditional注解,條件符合才會起效
在這里插入圖片描述
然后為什么說2.2.1版本默認是Hikari作為Datasource的?可以看一下項目的依賴圖,可以看出默認引入了Hikari的jar
在這里插入圖片描述
而且條件都符合,所以HikariDataSource就會進行自動配置
在這里插入圖片描述
源碼里用import引入了一個DataSourceInitializationConfiguration類,看其命名,應該是個初始化配置類
在這里插入圖片描述
挑重點,如圖,很明顯要用了Spring框架很重要的后置處理器,還有一個DataSourceInitializerInvoker類
在這里插入圖片描述
DataSourceInitializerInvoker類是做什么的?看其源碼應該是一個初始化操作的監聽器類,主要操作由DataSourceInitializer執行
在這里插入圖片描述
DataSourceInitializer源碼,里面有很多操作都是進行schema腳本的操作,只要非isEnabled就可以執行
在這里插入圖片描述
只要兩個條件符合就執行,DataSourceInitializationMode屬性,看起來是通過配置文件獲取的
在這里插入圖片描述
getScripts,獲取對應的腳本
在這里插入圖片描述
讀取schema腳本,所以可以看出只要將一些sql文件放在resources即可,默認文件命名為schema.sql,schema‐all.sql;
在這里插入圖片描述
再通過資料,確認了這個類確實是執行一些初始化schema腳本的,根據application提示,發現有個屬性,將其改為always即可
在這里插入圖片描述

改為embedded是不能執行的,雖然源碼里代碼是這樣的
在這里插入圖片描述
還有這個關鍵代碼,從配置spring.datasource.schema獲取信息,

List<Resource> scripts = getScripts("spring.datasource.schema", this.properties.getSchema(), "schema");

在這里插入圖片描述

private List<Resource> getResources(String propertyName, List<String> locations, boolean validate) {
		List<Resource> resources = new ArrayList<>();
		for (String location : locations) {
			for (Resource resource : doGetResources(location)) {
				if (resource.exists()) {
					resources.add(resource);
				}
				else if (validate) {
					throw new InvalidConfigurationPropertyValueException(propertyName, resource,
							"The specified resource does not exist.");
				}
			}
		}
		return resources;
	}

location就是一個字符類型的位置信息,所以可以使用如下配置,顯然就可以自定義schema腳本,不需要固定為schema.sql或者schema-all.sql
在這里插入圖片描述

代碼例子下載:github下載鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM