java--開源數據庫連接池(dbcp數據源)

現在很多WEB服務器(Weblogic, WebSphere, Tomcat)都提供了DataSoruce的實現,即連接池的實現。通常我們把DataSource的實現,按其英文含義稱之爲數據源,數據源中都包含了數據庫連接池的實現。
也有一些開源組織提供了數據源的獨立實現:
        DBCP 數據庫連接池
        C3P0 數據庫連接池
實際應用時不需要編寫連接數據庫代碼,直接從數據源獲得數據庫的連接。程序員編程時也應儘量使用這些數據源的實現,以提升程序的數據庫訪問性能。
DBCP數據源
DBCP 是 Apache 軟件基金組織下的開源連接池實現,使用DBCP數據源,應用程序應在系統中增加如下兩個 jar 文件:
        Commons-dbcp.jar:連接池的實現
        Commons-pool.jar:連接池實現的依賴庫
Tomcat 的連接池正是採用該連接池來實現的。該數據庫連接池既可以與應用服務器整合使用,也可由應用程序獨立使用。

dbcp數據庫連接池的兩種實現方式

package cn.hncu.dbcp;

import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test;

public class DbcpPoolDemo {

    //dbcp數據庫連接池----BasicDataSource類對象

    //使用配置文件的方式--利用BasicDataSourceFactory工廠類+Properties的方式創建,參數直接從配置文件讀取
    @Test
    public void demo2() throws Exception{
        Properties p=new Properties();
        //src目錄下的--配置文件放在classpath下,則可用下面一行來獲取
//      p.load(DbcpPoolDemo.class.getClassLoader().getResourceAsStream("dbcp.properties"));
        //配置文件和當前類放在一起
        p.load(DbcpPoolDemo.class.getResourceAsStream("dbcp2.properties"));
        DataSource pool=BasicDataSourceFactory.createDataSource(p);
//      Connection con=pool.getConnection();
//      System.out.println("con:"+con);
        for(int i=0;i<30;i++){//默認是八個,可以通過資源文件(dbcp2.properties)更改 

            Connection con=pool.getConnection();
            System.out.println(con.hashCode());//輸出8個(pool.getMaxActive())之後就阻塞了
        }

    }
    @Test//純Java方式 ---利用空參構造方式BasicDataSource()創建,然後通過setter方法手動設置參數
    public void demo1() throws Exception{
        BasicDataSource pool=new BasicDataSource();
        pool.setDriverClassName("com.mysql.jdbc.Driver");
        pool.setUrl("jdbc:mysql://127.0.0.1:3306/hncu?useUnicode=true&characterEncoding=utf-8");
        pool.setUsername("root");
        pool.setPassword("1234");
//      Connection con=pool.getConnection();
//      System.out.println(con);

        System.out.println("初始連接的個數:"+pool.getInitialSize());//0
        System.out.println("最多能有幾個在用的連接:"+pool.getMaxActive());//8
        System.out.println("最多空閒多長時間(若沒使用該連接就收回):"+pool.getMaxIdle());//8
        System.out.println("最多等待多長時間(若沒獲得連接就拋出異常):"+pool.getMaxWait());//-1
        //可以自己更改池的參數
        pool.setMaxActive(10);
        /*
         * 以下測試從池獲取多個連接
         */
        for(int i=0;i<15;i++){
            Connection con=pool.getConnection();
            System.out.println(con.hashCode());//輸出8個(pool.getMaxActive())之後就阻塞了
            if(i%2==0){//dbcp池中如果有最近使用的連接con,就不會新開一個連接con,而是使用最近用的con
                con.close();
            }
        }
        System.out.println("Over....");
    }
}

dbcp.properties放在src目錄下

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/hncu?useUnicode=true&characterEncoding=utf-8
username=root
password=1234
size=3

開源數據庫連接池

package cn.hncu.dbcp;

import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class DbcpUtils {
    //本地線程管理對象,用於實現: 同一個線程獲取的連接是同一個
    private static ThreadLocal<Connection> t = new ThreadLocal<Connection>();

    private static DataSource pool = null;
    static{
        Properties p = new Properties();
        try {
            //配置文件和當前類放在一起
            p.load(DbcpUtils.class.getResourceAsStream("dbcp2.properties"));

            pool= BasicDataSourceFactory.createDataSource(p);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConn() {
        //先從t中拿,如果有就拿出去,如果沒有再到池中拿且把該對象放到t中
        Connection con = t.get();
        if(con==null){
            try {
                con=pool.getConnection();
                t.set(con); //放到t中
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }
        System.out.println("獲取一個連接:"+con);
        return con;
    }

}

dbcp2.properties和當前類放在一起

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/hncu?useUnicode=true&characterEncoding=utf-8
username=root
password=1234
maxActive=15
package cn.hncu.test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.UUID;

import org.junit.Test;

import cn.hncu.dbcp.DbcpUtils;

public class DbcpTest {

    @Test
    public void demo() throws Exception{
        Connection con=DbcpUtils.getConn();
        System.out.println("demo-con:"+con);
        try {
            con.setAutoCommit(false);
            saveStud();
            saveStud2();
            con.commit();
            System.out.println("提交一個事務...");
        } catch (SQLException e) {
            con.rollback();
            System.out.println("回滾一個事務...");
        }finally{
            con.setAutoCommit(true);//還原現場
            con.close();
        }

    }

    public void saveStud() throws Exception{
        Connection con=DbcpUtils.getConn();
        System.out.println("saveStud-con:"+con);
        String sql="INSERT INTO stud VALUES(?,?)";
        PreparedStatement pst=con.prepareStatement(sql);
        for(int i=0;i<2;i++){
            String id=UUID.randomUUID().toString().replace("-", "");
            pst.setString(1, id);
            pst.setString(2, "stud"+i);
            pst.addBatch();
        }
        pst.executeBatch();
    }
    public void saveStud2() throws Exception{
        Connection con=DbcpUtils.getConn();
        System.out.println("saveStud2-con:"+con);
        String sql="insert into stud values(?,?)";
        PreparedStatement pst=con.prepareStatement(sql);
        for(int i=3;i<5;i++){
            String id=UUID.randomUUID().toString().replace("-", "");
            pst.setString(1, id);
//          pst.setString(1, "70e56717e7634c9c85aefcad6560afd1");//測試事務回滾
            pst.setString(2, "stud"+i);
            pst.addBatch();
        }
        pst.executeBatch();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章