Spring Boot的數據源與連接池
- ? Create by [email protected] 2018-8-2
一:依賴
使用Spring Boot的默認數據源spring.datasource
只需要導入如下依賴:
<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>
或者你使用的是JPA:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
查看JPA的依賴關系,如圖,其中已經包含JDBC。
二:數據源
配置我們的Mysql數據庫連接信息:
spring: ??datasource: ????username:?root ????password:?123456 ????url:?jdbc:mysql://192.168.15.22:3306/jdbc ????driver‐class‐name:?com.mysql.jdbc.Driver
1.如何查看當前數據源?
編寫單元測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class RobotsApplicationTests {
@Autowired
DataSource dataSource;
@Test
public void test(){
System.out.println(dataSource.getClass());
}
}
查看打印:
class org.apache.tomcat.jdbc.pool.DataSource
總結
所以這段配置的效果就是,默認是用org.apache.tomcat.jdbc.pool.DataSource作為數據源,
且數據源的相關配置都在DataSourceProperties裏面,如下:
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties
implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {
...
private String name = "testdb";
private String driverClassName;
private String url;
private String username;
private String password;
.....
2.自動配置原理
找到org.springframework.boot.autoconfigure.jdbc
包下的DataSourceConfiguration
類
abstract class DataSourceConfiguration {
@ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true)
static class Tomcat extends DataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.tomcat")
public org.apache.tomcat.jdbc.pool.DataSource dataSource(
DataSourceProperties properties) {
org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(
properties, org.apache.tomcat.jdbc.pool.DataSource.class);
DatabaseDriver databaseDriver = DatabaseDriver
.fromJdbcUrl(properties.determineUrl());
String validationQuery = databaseDriver.getValidationQuery();
if (validationQuery != null) {
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery(validationQuery);
}
return dataSource;
}
}
......
以上就是自動配置代碼,原理大概是如果在classpath下存在org.apache.tomcat.jdbc.pool.DataSource.class
類,並且在配置文件中指定spring.datasource.type
的值為org.apache.tomcat.jdbc.pool.DataSource
,或者不寫都會認為可以通過。只有通過才會進入這段配置代碼,才能註入DataSource
Bean。
SpringBoot默認可以支持;
org.apache.tomcat.jdbc.pool.DataSource、HikariDataSource、BasicDataSource、
當然了,除了Tomcat數據源依賴自帶,其他都是缺少狀態。
3.自定義數據源
找到這個類的最下面,如果spring.datasource.type
的值不屬於上面的幾個,那麽可以自己定義數據源:
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {
@Bean
public DataSource dataSource(DataSourceProperties properties) {
//使用DataSourceBuilder創建數據源,利用反射創建響應type的數據源,並且綁定相關屬性
return properties.initializeDataSourceBuilder().build();
}
}
4.自動執行SQL語句
打開DataSourceAutoConfiguration自動配置類,在自動配置DataSource時會註入DataSourceInitializer
,繼續打開該類,
我們發現該類有一個方法被註解@PostConstruct
,這個註解用於需要在依賴註入完成後執行任何初始化的方法上。該初始化方法調用了runSchemaScripts();
該方法的第一句就調用 getScripts()
方法,獲取SQL腳本,如圖:
所以我們想要初始化一些數據庫腳本,可以依照這個規則
schema‐*.sql、data‐*.sql
例如:
schema.sql,schema‐all.sql;
也可以使用如下指定具體位置
??schema: ???
??????‐?classpath:department.sql
作用:
1)、runSchemaScripts();運行建表語句;
2)、runDataScripts();運行插入數據的sql語句;
5.操作數據庫
自動配置了JdbcTemplate操作數據庫,示例:
@RunWith(SpringRunner.class)
@SpringBootTest
public class RobotsApplicationTests {
@Autowired
JdbcTemplate jdbcTemplate;
@Test
public void test(){
jdbcTemplate.queryForList("SELECT * FROM user");
}
}
三:連接池
為什麽要把數據源和連接池放在一起講,因為當我們使用了如上所述的默認數據源之後,那麽已默認啟用了數據庫鏈接池。 換句話說,你根本不需要關心連接池,它本來就有!
1.默認連接池規則
Tomcat7之前,Tomcat本質應用了DBCP連接池技術來實現的JDBC數據源,但在Tomcat7之後,Tomcat提供了新的JDBC連接池方案,作為DBCP的替換或備選方案,解決了許多之前使用DBCP的不利之處,並提高了性能。詳細請參考:http://wiki.jikexueyuan.com/project/tomcat/tomcat-jdbc-pool.html
Spring Boot為我們準備了最佳的數據庫連接池方案,只需要在屬性文件(例如application.properties)中配置需要的連接池參數即可。
在引入spring-boot-starter-jdbc後,內部包含了tomcat-jdbc包,裏面有tomcat連接池.然後通過自動配置DataSourceAutoConfigurer創建DataSource對象。
SpringBoot創建默認DataSource時,規則如下:
優先尋找創建Tomcat連接池
如果沒有Tomcat連接池,會查找創建HikariCP
如果沒有HikariCP連接池,會查找創建dbcp
如果沒有dbcp連接池,會查找創建dbcp2
可以使用spring.datasource.type屬性指定連接池類型
spring.datasource.type=org.apache.commons.dbcp.BasicDataSource
2.控制連接池行為
在數據源那一講中,我們已經知道Spring data默認使用tomcat-jdbc時,所以直接在application.yml增加配置項spring.datasource.tomcat.*來控制鏈接池的行為。比如如下配置。
spring:
datasource:
url: jdbc:mysql://localhost:3306/jackieathome?useSSL=false
username: root
password: mypassword
# 6.x版本的MySQL JDBC驅動類為com.mysql.cj.jdbc.Driver
# 5.X版本的MySQL JDBC驅動類為com.mysql.jdbc.Driver
driver-class-name: com.mysql.cj.jdbc.Driver
tomcat:
max-wait: 10000
max-active: 30
test-on-borrow: true
max-idle: 5
3.Tomcat常用屬性
屬性 | 描述 |
---|---|
defaultAutoCommit |
(布爾值)連接池所創建的連接默認自動提交狀態。如果未設置,則默認采用 JDBC 驅動的缺省值(如果未設置,則不會調用 setAutoCommit 方法)。 |
defaultReadOnly |
(布爾值)連接池所創建的連接默認只讀狀態。如果未設置,將不會調用 setReadOnly 方法。(有些驅動並不支持只讀模式,比如:informix) |
defaultTransactionIsolation |
(字符串)連接池所創建的連接的默認事務隔離狀態。取值範圍為:(參考 javadoc) NONE``READ_COMMITTED``READ_UNCOMMITTED``REPEATABLE_READ``SERIALIZABLE 如果未設置該值,則不會調用任何方法,默認為 JDBC 驅動。 |
defaultCatalog |
(字符串)連接池所創建的連接的默認catalog。 |
driverClassName |
(字符串)所要使用的 JDBC 驅動的完全限定的 Java 類名。該驅動必須能從與 tomcat-jdbc.jar 同樣的類加載器訪問 |
username |
(字符串)傳入 JDBC 驅動以便建立連接的連接用戶名。註意,DataSource.getConnection(username,password) 方法默認不會使用傳入該方法內的憑證,但會使用這裏的配置信息。可參看 alternateUsernameAllowed 了解更多詳情。 |
password |
(字符串)傳入 JDBC 驅動以便建立連接的連接密碼。註意,DataSource.getConnection(username,password) 方法默認不會使用傳入該方法內的憑證,但會使用這裏的配置信息。可參看 alternateUsernameAllowed 了解更多詳情。 |
maxActive |
(整形值)池同時能分配的活躍連接的最大數目。默認為 100 。 |
maxIdle |
(整型值)池始終都應保留的連接的最大數目。默認為 maxActive:100 。會周期性檢查空閑連接(如果啟用該功能),留滯時間超過 minEvictableIdleTimeMillis 的空閑連接將會被釋放。(請參考 testWhileIdle ) |
minIdle |
(整型值)池始終都應保留的連接的最小數目。如果驗證查詢失敗,則連接池會縮減該值。默認值取自 initialSize:10 (請參考 testWhileIdle )。 |
initialSize |
(整型值)連接器啟動時創建的初始連接數。默認為 10 。 |
maxWait |
(整型值)在拋出異常之前,連接池等待(沒有可用連接時)返回連接的最長時間,以毫秒計。默認為 30000 (30 秒) |
testOnBorrow |
(布爾值)默認值為 false 。從池中借出對象之前,是否對其進行驗證。如果對象驗證失敗,將其從池中清除,再接著去借下一個。註意:為了讓 true 值生效,validationQuery 參數必須為非空字符串。為了實現更高效的驗證,可以采用 validationInterval 。 |
testOnReturn |
(布爾值)默認值為 false 。將對象返回池之前,是否對齊進行驗證。註意:為了讓 true 值生效,validationQuery 參數必須為非空字符串。 |
testWhileIdle |
(布爾值)是否通過空閑對象清除者(如果存在的話)驗證對象。如果對象驗證失敗,則將其從池中清除。註意:為了讓 true 值生效,validationQuery 參數必須為非空字符串。該屬性默認值為 false ,為了運行池的清除/測試線程,必須設置該值。(另請參閱 timeBetweenEvictionRunsMillis ) |
validationQuery |
(字符串)在將池中連接返回給調用者之前,用於驗證這些連接的 SQL 查詢。如果指定該值,則該查詢不必返回任何數據,只是不拋出 SQLException 異常。默認為 null 。實例值為:SELECT 1 (MySQL) select 1 from dual (Oracle) SELECT 1 (MySQL Server)。 |
validationQueryTimeout |
(整型值)連接驗證失敗前的超時時間(以秒計)。通過在執行 validationQuery 的語句上調用 java.sql.Statement.setQueryTimeout(seconds) 來實現。池本身並不會讓查詢超時,完全是由 JDBC 來強制實現。若該值小於或等於 0,則禁用該功能。默認為 -1 。 |
validatorClassName |
(字符串)實現 org.apache.tomcat.jdbc.pool.Validator 接口並提供了一個無參(可能是隱式的)構造函數的類名。如果指定該值,將通過該類來創建一個 Validator 實例來驗證連接,代替任何驗證查詢。默認為 null ,範例值為:com.mycompany.project.SimpleValidator 。 |
timeBetweenEvictionRunsMillis |
(整型值)空閑連接驗證/清除線程運行之間的休眠時間(以毫秒計)。不能低於 1 秒。該值決定了我們檢查空閑連接、廢棄連接的頻率,以及驗證空閑連接的頻率。默認為 5000 (5 秒) |
numTestsPerEvictionRun |
(整型值)Tomcat JDBC 連接池沒有用到這個屬性。 |
minEvictableIdleTimeMillis |
(整型值)在被確定應被清除之前,對象在池中保持空閑狀態的最短時間(以毫秒計)。默認為 60000 (60 秒) |
accessToUnderlyingConnectionAllowed |
(布爾值)沒有用到的屬性。可以在歸入池內的連接上調用 unwrap 來訪問。參閱 javax.sql.DataSource 接口的相關介紹,或者通過反射調用 getConnection ,或者將對象映射為 javax.sql.PooledConnection 。 |
removeAbandoned |
(布爾值)該值為標誌(Flag)值,表示如果連接時間超出了 removeAbandonedTimeout ,則將清除廢棄連接。如果該值被設置為 true ,則如果連接時間大於 removeAbandonedTimeout ,該連接會被認為是廢棄連接,應予以清除。若應用關閉連接失敗時,將該值設為 true 能夠恢復該應用的數據庫連接。另請參閱 logAbandoned 。默認值為 false 。 |
removeAbandonedTimeout |
(整型值)在廢棄連接(仍在使用)可以被清除之前的超時秒數。默認為 60 (60 秒)。應把該值設定為應用可能具有的運行時間最長的查詢。 |
logAbandoned |
(布爾值)標誌能夠針對丟棄連接的應用代碼,進行堆棧跟蹤記錄。由於生成堆棧跟蹤,對廢棄連接的日誌記錄會增加每一個借取連接的開銷。默認為 false |
connectionProperties |
(字符串)在建立新連接時,發送給 JDBC 驅動的連接屬性。字符串格式必須為:[propertyName=property;]*。註意:user 與 password 屬性會顯式傳入,因此這裏並不需要包括它們。默認為 null。 |
poolPreparedStatements |
(布爾值)未使用的屬性 |
maxOpenPreparedStatements |
(整型值)未使用的屬性 |
4.Tomcat JDBC 增強屬性
屬性 | 描述 |
---|---|
initSQL |
字符串值。當連接第一次創建時,運行的自定義查詢。默認值為 null 。 |
jdbcInterceptors |
字符串。繼承自類 org.apache.tomcat.jdbc.pool.JdbcInterceptor 的子類類名列表,由分號分隔。關於格式及範例,可參見下文的配置 JDBC 攔截器。 這些攔截器將會插入到 java.sql.Connection 對象的操作隊列中。 預定義的攔截器有: org.apache.tomcat.jdbc.pool.interceptor``ConnectionState ——記錄自動提交、只讀、catalog以及事務隔離級別等狀態。org.apache.tomcat.jdbc.pool.interceptor``StatementFinalizer ——記錄打開的語句,並當連接返回池後關閉它們。 有關更多預定義攔截器的詳盡描述,可參閱JDBC 攔截器 |
validationInterval |
長整型值。為避免過度驗證而設定的頻率時間值(以秒計)。最多以這種頻率運行驗證。如果連接應該進行驗證,但卻沒能在此間隔時間內得到驗證,則會重新對其進行驗證。默認為 30000 (30 秒)。 |
jmxEnabled |
布爾值。是否利用 JMX 註冊連接池。默認為 true 。 |
fairQueue |
布爾值。假如想用真正的 FIFO 方式公平對待 getConnection 調用,則取值為 true 。對空閑連接列表將采用 org.apache.tomcat.jdbc.pool.FairBlockingQueue 實現。默認值為 true 。如果想使用異步連接獲取功能,則必須使用該標誌。 設置該標誌可保證線程能夠按照連接抵達順序來接收連接。 在性能測試時,鎖及鎖等待的實現方式有很大差異。當 fairQueue=true 時,根據所運行的操作系統,存在一個決策過程。假如系統運行在 Linux 操作系統(屬性 os.name = linux )上,為了禁止這個 Linux 專有行為,但仍想使用公平隊列,那麽只需在連接池類加載之前,將 org.apache.tomcat.jdbc.pool.FairBlockingQueue.ignoreOS=true 添加到系統屬性上。 |
abandonWhenPercentageFull |
整型值。除非使用中連接的數目超過 abandonWhenPercentageFull 中定義的百分比,否則不會關閉並報告已廢棄的連接(因為超時)。取值範圍為 0-100。默認值為 0,意味著只要達到 removeAbandonedTimeout ,就應關閉連接。 |
maxAge |
長整型值。連接保持時間(以毫秒計)。當連接要返回池中時,連接池會檢查是否達到 now - time-when-connected > maxAge 的條件,如果條件達成,則關閉該連接,不再將其返回池中。默認值為 0 ,意味著連接將保持開放狀態,在將連接返回池中時,不會執行任何年齡檢查。 |
useEquals |
布爾值。如果想讓 ProxyConnection 類使用 String.equals ,則將該值設為 true ;若想在對比方法名稱時使用 == ,則應將其設為 false 。該屬性不能用於任何已添加的攔截器中,因為那些攔截器都是分別配置的。默認值為 true 。 |
suspectTimeout |
整型值。超時時間(以秒計)。默認值為 0 。 類似於 removeAbandonedTimeout ,但不會把連接當做廢棄連接從而有可能關閉連接。如果 logAbandoned 設為 true ,它只會記錄下警告。如果該值小於或等於 0,則不會執行任何懷疑式檢查。如果超時值大於 0,而連接還沒有被廢棄,或者廢棄檢查被禁用時,才會執行懷疑式檢查。如果某個連接被懷疑到,則記錄下 WARN 信息並發送一個 JMX 通知。 |
rollbackOnReturn |
布爾值。如果 autoCommit==false ,那麽當連接返回池中時,池會在連接上調用回滾方法,從而終止事務。默認值為 false 。 |
commitOnReturn |
布爾值。如果 autoCommit==false ,那麽當連接返回池中時,池會在連接上調用提交方法,從而完成事務;如果 rollbackOnReturn==true ,則忽略該屬性。默認值為 false 。 |
alternateUsernameAllowed |
布爾值。出於性能考慮,JDBC 連接池默認會忽略 DataSource.getConnection(username,password) 調用,只返回之前池化的具有全局配置屬性 username 和 password 的連接。 但經過配置,連接池還可以允許使用不同的憑證來請求每一個連接。為了啟用這項在DataSource.getConnection(username,password) 調用中描述的功能,只需將 alternateUsernameAllowed 設為 true 。 如果你請求一個連接,憑證為 user 1/password 1,而連接之前使用的是 user 2/password 2 憑證,那麽連接將被關閉,重新利用請求的憑證來開啟。按照這種方式,池的容量始終以全局級別管理,而不是限於模式(schema)級別。 默認值為 false 。 該屬性作為一個改進方案,被添加到了 bug 50025 中。 |
dataSource |
(javax.sql.DataSource)將數據源註入連接池,從而使池利用數據源來獲取連接,而不是利用 java.sql.Driver 接口來建立連接。它非常適於使用數據源(而非連接字符串)來池化 XA 連接或者已建立的連接時。默認值為 null 。 |
dataSourceJNDI |
字符串。在 JNDI 中查找的數據源的 JNDI 名稱,隨後將用於建立數據庫連接。參看 datasource 屬性的介紹。默認值為 null 。 |
useDisposableConnectionFacade |
布爾值。如果希望在連接上放上一個門面對象,從而使連接在關閉後無法重用,則要將值設為 true 。這能防止線程繼續引用一個已被關閉的連接,並繼續在連接上查詢。默認值為 true 。 |
logValidationErrors |
布爾值。設為 true 時,能將驗證階段的錯誤記錄到日誌文件中,錯誤會被記錄為 SEVERE。考慮到了向後兼容性,默認值為 false 。 |
propagateInterruptState |
布爾值。傳播已中斷的線程(還沒有清除中斷狀態)的中斷狀態。考慮到了向後兼容性,默認值為 false 。 |
ignoreExceptionOnPreLoad |
布爾值。在初始化池時,是否忽略連接創建錯誤。取值為 true 時表示忽略;設為 false 時,拋出異常,從而宣告池初始化失敗。默認值為 false 。 |
本文原創,轉載請註明出處!
Spring Boot的數據源與連接池