什麼是鏈接?java
鏈接,是咱們的編程語言與數據庫交互的一種方式。咱們常常會聽到這麼一句話「數據庫鏈接很昂貴「。mysql
有人接受這種說法,殊不知道它的真正含義。所以,下面我將解釋它到底是什麼。[若是你已經知道了,你能夠跳到它的工做原理部分]sql
建立鏈接的代碼片斷:數據庫
?編程
1數組 2dom 3編程語言 |
String connUrl = "jdbc:mysql://your.database.domain/yourDBname" ; ide Class.forName( "com.mysql.jdbc.Driver" ); url Connection con = DriverManager.getConnection (connUrl); |
當咱們建立了一個Connection對象,它在內部都執行了什麼:
1.「DriverManager」檢查並註冊驅動程序,
2.「com.mysql.jdbc.Driver」就是咱們註冊了的驅動程序,它會在驅動程序類中調用「connect(url…)」方法。
3.com.mysql.jdbc.Driver的connect方法根據咱們請求的「connUrl」,建立一個「Socket鏈接」,鏈接到IP爲「your.database.domain」,默認端口3306的數據庫。
4.建立的Socket鏈接將被用來查詢咱們指定的數據庫,並最終讓程序返回獲得一個結果。
爲何昂貴?
如今讓咱們談談爲何說它「昂貴「。
若是建立Socket鏈接花費的時間比實際的執行查詢的操做所花費的時間還要更長。
這就是咱們所說的「數據庫鏈接很昂貴」,由於鏈接資源數是1,它須要每次建立一個Socket鏈接來訪問DB。
所以,咱們將使用鏈接池。
鏈接池初始化時建立必定數量的鏈接,而後從鏈接池中重用鏈接,而不是每次建立一個新的。
怎樣工做?
接下來咱們來看看它是如何工做,以及如何管理或重用現有的鏈接。
咱們使用的鏈接池供應者,它的內部有一個鏈接池管理器,當它被初始化:
1.它建立鏈接池的默認大小,好比指定建立5個鏈接對象,並把它存放在「可用」狀態的任何集合或數組中。
例如,代碼片斷:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
... String connUrl = "jdbc:mysql://your.database.domain/yourDBname" ; String driver = "com.mysql.jdbc.Driver" ; private Map<java.sql.Connection, String> connectionPool = null ; private void initPool() { try { connectionPool = new HashMap<java.sql.Connection, String>(); Class.forName(driver); java.sql.Connection con = DriverManager.getConnection(dbUrl); for ( int poolInd = poolSize; poolInd < 0 ; poolInd++) { connectionPool.put(con, "AVAILABLE" ); } } ... |
2.當咱們調用connectionProvider.getConnection(),而後它會從集合中獲取一個鏈接,固然狀態也會更改成「不可用」。
例如,代碼片斷:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
... public java.sql.Connection getConnection() throws ClassNotFoundException, SQLException { boolean isConnectionAvailable = true ; for (Entry<java.sql.Connection, String> entry : connectionPool.entrySet()) { synchronized (entry) { if (entry.getValue()== "AVAILABLE" ) { entry.setValue( "NOTAVAILABLE" ); return (java.sql.Connection) entry.getKey(); } isConnectionAvailable = false ; } } if (!isConnectionAvailable) { Class.forName(driver); java.sql.Connection con = DriverManager.getConnection(connUrl); connectionPool.put(con, "NOTAVAILABLE" ); return con; } return null ; } ... |
3.當咱們關閉獲得的鏈接,ConnectionProvider是不會真正關閉鏈接。相反,只是將狀態更改成「AVAILABLE」。
例如,代碼片斷:
?
1 2 3 4 5 6 7 8 9 10 11 12 |
... public void closeConnection(java.sql.Connection connection) throws ClassNotFoundException, SQLException { for (Entry<java.sql.Connection, String> entry : connectionPool.entrySet()) { synchronized (entry) { if (entry.getKey().equals(connection)) { //Getting Back the conncetion to Pool entry.setValue( "AVAILABLE" ); } } } } ... |
基本上鍊接池的實際工做原理就是這樣,但也有可能使用不一樣的方式。
如今,你可能有一個問題,咱們是否能夠創造咱們本身的鏈接池機制?
個人建議是使用已經存在的鏈接池機制,像C3P0,DBCP等。