使用JDBC是怎麼保證資料庫用戶端和資料庫服務端進行連接配接的?
通過代碼:
conn=DriverManager.getConnection(url, username, password);
JDBC通過這條代碼方法的調用建立了一條用戶端應用程式到後端資料庫的實體連接配接。期間發生了大量的基于TCP的用戶端與服務端的互動。

由于跨機器的網絡傳輸是由較大的網絡開銷的,是以時間花銷很大。
傳統的多線程JDBC服務中,我們每進行一次服務都需要配置設定一個線程,每一個線程去建立一個資料庫連接配接,當這條服務結束之後,該線程和該資料庫連接配接都将被銷毀。
當我們需要下一次資料庫服務時,再次建立新的線程和資料庫連接配接。
這樣每次在建立資料庫連接配接上浪費了大量的時間,使用者的相應時間變得很慢。
連接配接池的出現就是為了解決這個問題,連接配接池實作了資料庫連接配接(connection對象)的複用,當一個線程處理完相應程式服務,随後不緊接着銷毀資料庫連接配接,而是把它交給下一個線程使用。這樣就避免了多次建立資料庫連接配接而浪費時間的問題出現。實作了從每個線程建立資料庫連接配接到每個線程租用資料庫連接配接的轉變。
MySQL資料庫内部是怎麼配置設定各種連接配接的?
在MySQL資料庫中也存在着記憶體限制,當配置設定的資料庫連接配接過多,會增加資料庫記憶體的占用,加劇各種鎖的沖突,占用資料庫資源,甚至造成資料庫崩潰。是以一般在MySQL資料庫中設定最大連接配接數。
但是,為了保證不出現上述問題,我們可以在連接配接請求到達資料庫之前進行限流,保證資料庫資源的優化利用,效率至上。連接配接池就起到了這個作用:限制連接配接。
連接配接池到底是什麼?
連接配接池本質上就是一組java的jar包,介于java應用和JDBC資料庫實體連接配接之間,幫助應用程式來管理資料庫連接配接,通過連接配接池暴露的接口,應用程式可以擷取JDBC連接配接,使用完後
将JDBC歸還給連接配接池,供下一個線程使用。
在連接配接池中,資料庫連接配接不足的時候,會自動建立連接配接;同時當空閑連接配接過多時也會自動銷毀連接配接。
當多個線程同時通路時,連接配接池還提供了排隊等待的功能。保證了應用程式有序地擷取資料庫連接配接。
連接配接池怎麼使用?(相關示例代碼貼在後面)
以現在最受歡迎的JDCP連接配接池為例。
相關jar包下載下傳位址:
其中,有兩種jar版本,windows推薦下載下傳.zip版
關于兩版的差别,參考:
1)建立一個連接配接池對象(BasicDataSource):
因為JDCP的底層也是通過JDBC來實作的,是以我們需要告訴它相應的資訊。
通過BasicDataSource對象的一系列方法,來對連接配接池進行相關設定(基礎的和進階的)
相關進階配置:
連接配接數配置:
其中建議:将setMaxIdle()和setMinIdle()設定為相同的值。
DBCP定期檢查:
資料庫服務端為了釋放空閑等待的資源,預設會自動關閉空閑時間等待超過某個門檻值的連接配接。MySQL預設門檻值為8個小時。
但是,連接配接池不知道那個連接配接失效了,以防止連接配接池将失效的連接配接租借給應用程式,是以需要定期檢查。
保證連接配接池和資料庫服務端連接配接對象同步性,保證,連接配接池租借給應用程式的連接配接對象都是有效的。
建議:連接配接池中連接配接對象的銷毀時間門檻值要小于資料庫伺服器的銷毀時間門檻值。也就是說要在資料庫伺服器銷毀連接配接對象前,連接配接池先銷毀連接配接對象。保證連接配接池中連接配接對象的有效性。
2)通過BasicDataSource對象擷取資料庫連接配接對象(connection),然後跟JDBC中相似進行相關資料庫服務的調用。
注意,我們同樣需要在一系列操作過後,調用connection對象的close()方法。
但是連接配接池重寫了connection對象的close()方法,使得它的功能不再是将connection對象銷毀,而是将connection對象歸還給連接配接池,以供下一個線程調用。
相關示例代碼:
packagecom.java_JDCP;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;importorg.apache.commons.dbcp2.BasicDataSource;public classJDCP_test {private static String driverClassName="com.mysql.jdbc.Driver"; //資料庫驅動//連接配接資料庫的URL位址
private static String url="jdbc:mysql://localhost:3306/hellojdbc?useUnicode=true&characterEncoding=UTF-8";private static String username="root";//資料庫連接配接使用者名
private static String password="123456";//資料庫連接配接密碼
private static Connection conn=null;//資料庫連接配接對象
private static Statement stat=null;//語句陳述對象
private static ResultSet rs=null;//結果資料集
private static BasicDataSource ds=null;//BasicDataSource對象的相關初始化
public static voidjdcpInit(){
ds=new BasicDataSource();//建立BasicDataSource對象
ds.setUrl(url);
ds.setDriverClassName(driverClassName);
ds.setUsername(username);
ds.setPassword(password);
ds.setMaxIdle(2);//設定連接配接池中存在的最大連接配接對象的數量為2個
}public static voidmain(String[] args) {
jdcpInit();try{
conn=ds.getConnection();//從BasicDataSource對象中擷取資料庫連接配接//一下的操作就和JDBC相同了
stat=conn.createStatement();
rs=stat.executeQuery("select * from roster");while(rs.next())
System.out.println("name:"+rs.getString("name"));
}catch(SQLException e) {
e.printStackTrace();
}finally{try{if(rs!=null)
rs.close();if(stat!=null)
stat.close();if(conn!=null)
conn.close();//釋放資料庫連接配接,這裡連接配接池重寫了JDBC中資料庫連接配接(connection對象)的close()方法,原來是銷毀,現在是歸還給連接配接池,以供下個線程調用
} catch(SQLException e) {
e.printStackTrace();
}
}
}
}