今天來說一下數據庫鏈接池技術.其實這個名詞也就是聽起來高大上一點,實際上並非很複雜的內容,相信在個人講解下,而且本身實際的將代碼寫一遍以後,可以對這項技術有較爲深入的理解.廢話很少說,開始講解.java
所謂的數據庫鏈接池技術,就是用來分配,管理,釋放數據庫鏈接的.你也許會問,好像我直接用JDBC也可以實現這些功能吧. 嗯,你說的沒錯,JDBC確實也能夠,可是,你記不記得,咱們使用JDBC技術的時候,每次用完了,是否是都會將鏈接關閉;等到下一次再用的時候,是否是都得將數據庫鏈接再打開? 實際上,數據庫連接資源是十分寶貴的,咱們在小型的項目中還看不出來,在高併發的項目中,你會發現,這樣頻繁的打開和關閉數據庫連接是對服務器的一種摧殘,十分影響效率. 那麼,數據庫鏈接池是如何作的呢? 實現思路是這樣的:在每次有訪問的時候,數據庫鏈接池會給用戶分配一個數據庫鏈接,當用戶用完了鏈接以後,鏈接池再將鏈接回收,放回一個鏈接集合中. 原理就是這樣的,咱們來看一下這張圖加深印象 mysql
注意:下面的代碼我是分塊講解的,你一個個粘貼下來,最後確定也是能運行的,爲了方便,我會在講完以後,給出完整的實現代碼.sql
private final int init_count = 3; //初始化連接數目
private final int max_count = 6; //最大鏈接數
private int current_count = 0; //到當前鏈接數
複製代碼
private LinkedList<Connection> pool = new LinkedList<Connection>();
複製代碼
//構造函數,初始化連接放入鏈接池
public MyPool() {
for (int i=0;i<init_count;i++){
//記錄當前鏈接數
current_count++;
//createConnection是自定義的建立連接函數.
Connection connection = createConnection();
pool.addLast(connection);
}
}
複製代碼
public Connection createConnection() {
Class.forName("com.mysql.jdbc.Driver");
Connection connection =DriverManager.getConnection("jdbc:mysql://localhost:3306/keyan","root","root");
return connection;
}
複製代碼
public Connection getConnection() {
if (pool.size() > 0){
//removeFirst刪除第一個而且返回
//如今你必定看懂了我說的爲什要用LinkedList了吧,由於下面的這個
//removeFirst()方法會將集合中的第一個元素刪除,可是還會返回第一個元素
//這樣就省去了咱們不少沒必要要的麻煩
return pool.removeFirst();
}
if (current_count < max_count){
//記錄當前使用的鏈接數
current_count++;
//建立連接
return createConnection();
}
throw new RuntimeException("當前連接已經達到最大鏈接數");
}
複製代碼
public void releaseConnection(Connection connection){
if (pool.size() < init_count){
pool.addLast(connection);
current_count--;
}else {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
複製代碼
整個的實現過程就是這樣的,下面我把所有的代碼貼出來,方便你們學習.數據庫
//單元測試
@Test
public class MyPool {
private final int init_count = 3; //初始化連接數目
private final int max_count = 6; //最大
private int current_count = 0; //到當前鏈接數
//鏈接池,用來存放初始化連接
private LinkedList<Connection> pool = new LinkedList<Connection>();
//構造函數,初始化連接放入鏈接池
public MyPool() {
for (int i=0;i<init_count;i++){
//記錄當前鏈接數
current_count++;
Connection connection = createConnection();
pool.addLast(connection);
}
}
//建立新的鏈接
public Connection createConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/keyan","root","root");
return connection;
}catch (Exception e){
System.out.println("數據庫連接異常");
throw new RuntimeException();
}
}
//獲取連接
public Connection getConnection() {
if (pool.size() > 0){
//removeFirst刪除第一個而且返回
return pool.removeFirst();
}
if (current_count < max_count){
//記錄當前使用的鏈接數
current_count++;
//建立連接
return createConnection();
}
throw new RuntimeException("當前連接已經達到最大鏈接數");
}
//釋放連接
public void releaseConnection(Connection connection){
if (pool.size() < init_count){
pool.addLast(connection);
current_count--;
}else {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
複製代碼
本身跑了一遍代碼以後,你是否是發現原來看起來很複雜的技術,並不像咱們想得那樣? 好了,介紹完了基本的數據庫鏈接池技術原理以後,咱們就要介紹兩個開源的優秀的數據鏈接池技術. 其實,真正的數據庫鏈接池要考慮的東西比咱們剛纔寫的這玩意複雜,現階段不須要咱們寫這樣複雜的東西,不過若是你感興趣的話,能夠看看數據庫鏈接池的源代碼--沒錯,這兩個鏈接池都是開源的.OK,接下來就開始吧!tomcat
首先,sun公司規定,鏈接池技術需實現javax.sql.DataSource接口,也就是說,若是你要本身實現數據庫鏈接池,那麼就必須實現這個接口.是否是很牛比的樣子,實際上,做爲標準制定方,sun公司仍是有不少要求的,這是做爲標準制定者的權利,因此,企業或者國家每每會對一些關鍵技術標準的制定打得頭破血流.額,扯遠了...bash
其實,你可能不知道,若是你的tomcat通過特殊的配置,也是能夠做爲數據庫鏈接池使用的,由於tomcat內置的就是DBPC.. 想要使用DBPC,你必須導入三個jar文件:commons-dbcp2-2.2.0.jar,commons-pool2-2.5.0.jar,commons-logging-1.2.jar.我想,以你的聰明才智,想要獲取這三個jar文件,必定是小菜一疊,這是一個軟件開發者的必備技能--學會如何搜索. 使用起來就很是簡單了.使用的方式主要有兩種,一種是硬編碼的方式,就是本身手動設置各類參數,另一種就是配置相應的配置文件,而後載入就好了.服務器
BasicDataSource dataSource = new BasicDataSource();
//參數配置:初始化鏈接數,最大鏈接數,鏈接字符串,驅動,用戶,密碼
dataSource.setInitialSize(3); //最大初始化連接
dataSource.setMaxTotal(6); //最大連接
dataSource.setMaxIdle(3000); //最大空閒時間
dataSource.setUrl("jdbc:mysql:///keyan"); //url
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("root");
//獲取連接
Connection connection = dataSource.getConnection();
connection.prepareStatement("SELECT * FROM e_person").execute();
connection.close();
複製代碼
使用查詢的時候,只須要按照原來JDBC的操做方式就好了,這個沒啥好說的,按照我上面的配置方式實現就好了,必定不要忘記導入包.微信
//建立properties配置文件
Properties properties = new Properties();
//獲取文件流
InputStream in = DBCPTest.class.getResourceAsStream("db.properties");
//加載配置文件
properties.load(in);
//建立數據源對象
BasicDataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
//獲取連接
Connection connection = dataSource.getConnection();
ResultSet resultSet = connection.prepareStatement("SELECT * FROM e_person").executeQuery();
while (resultSet.next()){
System.out.println(resultSet.getString("work_name"));
}
connection.close();
複製代碼
上面是基本的操做流程,下面咱們看一下這個xml文件的配置 文件db.properties
併發
url=jdbc:mysql:///keyan
driverClassName=com.mysql.jdbc.Driver
username=root
password=root
initialSize=3
maxActive=6
maxIdle=3000
複製代碼
特別要注意的一點是,這個配置文件必定要放在和你的這DBPC類放在同一個包下. 都完成了以後,直接用就能夠了.函數
c3p0一樣是很是優秀的鏈接池技術,這個須要導入的文件比較少,只有一個c3p0-0.9.1.2.jar.本身去網站上找一下就行了. 使用c3p0一樣是有兩種方式,分別也是硬編碼方式和配置文件方式.
//配置相關的參數
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("jdbc:mysql:///keyan");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setUser("root");
dataSource.setPassword("root");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(6);
dataSource.setMaxIdleTime(1000);
Connection connection = dataSource.getConnection();
//sql語句
ResultSet resultSet = connection.prepareStatement("SELECT * FROM e_project").executeQuery();
while (resultSet.next()){
System.out.println(resultSet.getString("project_name"));
}
connection.close();
複製代碼
和上面同樣,簡單的使用一下就好了,知道如何使用就行.至於更加深層次的東西,有興趣的話慢慢研究吧.
ComboPooledDataSource dataSource = new ComboPooledDataSource();
Connection connection = dataSource.getConnection();
ResultSet resultSet = connection.prepareStatement("SELECT * FROM e_project").executeQuery();
while (resultSet.next()){
System.out.println(resultSet.getString("project_name"));
}
connection.close();
複製代碼
乍一看,你可能會問,不是配置文件方式實現嗎?沒錯,只是這個是隱式的調用,不須要你實現,只須要新建一個ComboPooledDataSource對象就好了,默認調用xml文件,文件路徑是src根目錄.也就是說,你只須要將配置文件寫在src目錄下就好了.重點是如何寫這個xml文件. 注意,文件名c3p0-config.xml,這個文件名不能改,必須是這個,文件路徑必須是src根目錄,不然讀取不到.
<c3p0-config>
<default-config>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">3</property>
<property name="maxPoolSize">6</property>
<property name="maxIdleTime">1000</property>
</default-config>
</c3p0-config>
複製代碼
配置文件的參數大致上用到的就這麼多,固然,你也能夠去找一下相關的資料,瞭解一下更加詳細的參數意義,這些參數,我麼平常使用足夠了.
因爲數據庫鏈接得以重用,避免了頻繁建立,釋放鏈接引發的大量性能開銷。在減小系統消耗的基礎上,另外一方面也增長了系統運行環境的平穩性。
數據庫鏈接池在初始化過程當中,每每已經建立了若干數據庫鏈接置於鏈接池中備用。此時鏈接的初始化工做均已完成。對於業務請求處理而言,直接利用現有可用鏈接,避免了數據庫鏈接初始化和釋放過程的時間開銷,從而減小了系統的響應時間
對於多應用共享同一數據庫的系統而言,可在應用層經過數據庫鏈接池的配置,實現某一應用最大可用數據庫鏈接數的限制,避免某一應用獨佔全部的數據庫資源
在較爲完善的數據庫鏈接池實現中,可根據預先的佔用超時設定,強制回收被佔用鏈接,從而避免了常規數據庫鏈接操做中可能出現的資源泄露
感謝您的閱讀,歡迎指正博客中存在的問題,也能夠跟我聯繫,一塊兒進步,一塊兒交流!
微信公衆號:進擊的程序狗 郵箱:roobtyan@outlook.com 我的博客:roobtyan.cn 掃描下面的二維碼關注我吧,你將收穫到意想不到的東西喲…… 給你們準備了一份很是棒的JAVA的視頻教程,從JAVA基礎一直到JAVAWEB,還有很是強大的項目實戰。 就在個人微信公衆號裏,回覆java就可查看,免費的呦!