1. 程式人生 > >JDBC秒變C3P0連線池——再加連線解耦

JDBC秒變C3P0連線池——再加連線解耦

從JDBC連線到C3P0資料庫連線池

在Java開發中,使用JDBC操作資料庫的四個步驟如下:

      ①載入資料庫驅動程式(Class.forName("資料庫驅動類");)
      ②連線資料庫(Connection con  = DriverManager.getConnection();)
      ③操作資料庫(PreparedStatement stat = con.prepareStatement(sql);stat.executeQuery();)
      ④關閉資料庫,釋放連線(con.close();)
  也就是說,所有的使用者都需要經過此四步進行操作,但是這四步之中有三步(①載入資料庫驅動程式、②連線資料庫、④關閉資料庫,釋放連線)對所有人都是一樣的,而所有人只有在操作資料庫上是不一樣,那麼這就造成了效能的損耗。
  那麼最好的做法是,準備出一個空間,此空間裡專門儲存著全部的資料庫連線,以後使用者用資料庫操作的時候不用再重新載入驅動、連線資料庫之類的,而直接從此空間中取走連線,關閉的時候直接把連線放回到此空間之中。       那麼此空間就可以稱為連線池(儲存所有的資料庫連線)   什麼是連線池:       連線池是建立和管理一個連線的緩衝池的技術,這些連線準備好被任何需要它們的執行緒使用;簡單理解為,當一輛汽車搬運東西,如果使用jdbc連線,(jdbc連線:與資料庫建立連線、傳送操作資料庫的語句並處理結果)那麼每一次都要去開啟資料庫,獲得連線,關閉資料庫。假設汽車搬運的東西是連線,那麼我可不可以每一次將連線搬運多個呢?而不是jdbc那樣,一次只搬運一個連線,然後就把汽車扔掉?這時候,使用連線池。   原理:   連線池基本的思想是在系統初始化的時候,將資料庫連線作為物件儲存在記憶體中,當用戶需要訪問資料庫時,並非建立一個新的連線,而是從連線池中取出一個已建立的空閒連線物件。使用完畢後,使用者也並非將連線關閉,而是將連線放回連線池中,以供下一個請求訪問使用。而連線的建立、斷開都由連線池自身來管理。同時,還可以通過設定連線池的引數來控制連線池中的初始連線數、連線的上下限數以及每個連線的最大使用次數、最大空閒時間等等。也可以通過其自身的管理機制來監視資料庫連線的數量、使用情況等。 為什麼要用到連線池     資料庫連線池的基本思想就是為資料庫連線建立一個“緩衝池”。預先在緩衝池中放入一定數量的連線,當需要建立資料庫連線時,只需從“緩衝池”中取出一個,使用完畢之後再放回去。我們可以通過設定連線池最大連線數來防止系統無盡的與資料庫連線。連線池主要由三部分組成:連線池的建立、連線池中連線的使用管理、連線池的關閉。資料庫連線池的最小連線數和最大連線數的設定要考慮到以下幾個因素:
  1. 最小連線數:是連線池一直保持的資料庫連線,所以如果應用程式對資料庫連線的使用量不大,將會有大量的資料庫連線資源被浪費.
  2. 最大連線數:是連線池能申請的最大連線數,如果資料庫連線請求超過次數,後面的資料庫連線請求將被加入到等待佇列中,這會影響以後的資料庫操作
  3. 如果最小連線數與最大連線數相差很大:那麼最先連線請求將會獲利,之後超過最小連線數量的連線請求等價於建立一個新的資料庫連線.不過,這些大於最小連線數的資料庫連線在使用完不會馬上被釋放,他將被放到連線池中等待重複使用或是空間超時後被釋放

下面這是c3p0資料庫連線池的執行機制  

(1)  程式初始化時建立連線池
(2) 使用時向連線池申請可用連線
(3) 使用完畢,將連線返還給連線池
(4) 程式退出時,斷開所有連線,並釋放資源

 

我用的開發工具是IDEA,建立的是Maven專案,要使用c3p0需要配置相關模組,如圖所示

 

<!-- mysql驅動-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.0.5</version>
    </dependency>
    <!-- c3p0 -->
    <dependency>
      <groupId>com.mchange</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.5.2</version>
    </dependency>

  

db.properties  檔名不能改, 必須放在src下  ,配置檔案中的key名稱不能變

 

 

 好,完成這些後開始連線資料庫

package jdbc;


import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.beans.PropertyVetoException;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class JDBCUtils {
    public void setConnection() throws SQLException, PropertyVetoException, IOException {
        //建立連線池
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        //載入配置檔案
        Properties properties = new Properties();
        properties.load(new FileInputStream("src/main/java/db.properties"));

        String driver = properties.getProperty("driver");
        String url = properties.getProperty("url");
        String username = properties.getProperty("username");
        String password = properties.getProperty("password");

        //獲得連線
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet res = null;


        dataSource.setDriverClass(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(username);
        dataSource.setPassword(password);

        conn = dataSource.getConnection();
        String sql = "select * from user";
        ps = conn.prepareStatement(sql);

        res = ps.executeQuery();
        while (res.next()){
            System.out.println(res.getInt("id")+" "+res.getString("username")+" "+res.getString("password"));
        }

    }

}

class text{
    public static void main(String[] args) throws PropertyVetoException, SQLException, IOException {
        JDBCUtils jdbcUtils = new JDBCUtils();
        jdbcUtils.setConnection();
    }
}

  

&n