數據庫學習筆記二十三 —— 數據庫連接池(DBCP、C3P0)

數據庫學習筆記二十三 —— 數據庫連接池(DBCP、C3P0)


數據庫連接池簡介

數據庫連接—>執行完畢—>釋放,其中連接—>釋放十分浪費系統資源
池化技術: 準備一些預先的資源,過來就連接預先準備好的
比如銀行,開門—>服務—>關門,如果每一個客戶都這樣的話浪費時間,所以開門後準備業務員服務,這樣就不用每一次都執行多餘的步驟了。開門—>業務員:等待客戶—>服務—>關門。那一個銀行最少需要多少個服務員呢?這就涉及到 最小連接數最大連接數就是業務最高承載上限,如果銀行的客戶很多,那麼客戶需要等待時間,這就是等待超時
例如:
最小連接數 10個(通常爲你常用的連接數)
最大連接數 15個
等待超時 100ms

實現簡介

編寫連接池,需要實現一個接口 DataSource

  • 開源數據源實現
    • DBCP
    • C3P0
    • Druid:阿里巴巴

使用了這些數據庫連接池後,我們在項目開發中就不需要編寫連接數據庫的代碼了


DBCP

需要用到的jar包

1.commons-dbcp 下載地址 http://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi
選擇好版本後點擊下載
在這裏插入圖片描述
解壓後用到這個文件
在這裏插入圖片描述
2.commons-pool 下載地址 http://commons.apache.org/proper/commons-pool/download_pool.cgi 下載方法同上,
用到的jar包是這個
在這裏插入圖片描述
把這兩個包粘貼到你idea項目的lib目錄下,如果你第一次導包就右擊lib目錄,選擇下圖選中的。
在這裏插入圖片描述
如果你的idea是版本比較新的,以前這個lib目錄Add as Library過了的話,直接粘貼進去就行了,
如果版本比較舊的話,可能需要如下圖刪除原來的Library裏的lib,然後再重新add一遍
右上角點擊項目結構,或者在左上角的File裏也有
在這裏插入圖片描述
在這裏插入圖片描述
打開後進行如下操作,然後再次將你的lib目錄右擊Add as Library
在這裏插入圖片描述
最後,總之只要你的lib目錄裏的jar包能如圖顯示分層,就能用了
在這裏插入圖片描述

代碼相關

在src下新建一個DBCP的配置文件dbcpconfig.properties(新建File,命名加後綴爲就行)

#連接設置 (這裏面的變量名,是DBCP數據源中定義好的,不要自己起名字)
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=false
username=root
password=123456

# 下面的全都可以不設置,不寫
#<!-- 初始化連接 -->
initialSize=10

#最大連接量
maxActive=50

#<!-- 最大空閒連接 --> 沒人用也空着不釋放,等超時之後再釋放
maxIdle=20

#<!-- 最小空閒連接 -->
minIdle=5

#<!-- 超時等待時間,以毫秒爲單位 60000/1000 = 60秒 -->
maxWait=60000


#JDBC驅動建立連接時附帶的連接屬性的格式必須爲這樣:[屬性名=property;]
#注意:"user"與"password"連個屬性會被明確傳遞,因此這裏不需要包含他們
connectionProperties=useUnicode=true;characterEncoding=UTF8

#指定由連接池所創建的連接的自動提交(auto-commit)狀態。
defaultAutoCommit=true

#driver default 指定由連接池所創建的連接的只讀(read-only) 狀態。
#如果沒有設置該值,則"setReadOnly"方法將不被調用。(某些驅動並不支持只讀模式,如: Informix)
defaultReadOnly=

#driver default 指定由連接池所創建的連接的事務級別(TransactionIsolation)。
#可用值爲下列之一: (詳情可見javadoc)NONE,READ_ UNCOMMITTED,READ_ COMMITTED,REPEATABLE_ READ等
defaultTransactionIsolation=READ_UNCOMMITTED

自己封裝一個工具類 JdbcUtils_DBCP

package pers.ylw.lesson05.utils;

import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils_DBCP {

    private static BasicDataSource dataSource = null;

    static {
        try{
            //通過反射獲取配置文件資源流
            InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
            Properties properties = new Properties();
            properties.load(in);

            //創建數據源 工廠模式-->創建對象
            dataSource = BasicDataSourceFactory.createDataSource(properties);

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //獲取連接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection(); //從數據源中獲取連接
    }

    //釋放連接資源
    public static void release(Connection conn, Statement st,ResultSet rs){
        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

使用這個 JdbcUtils_DBCP 工具類進行操作

package pers.ylw.lesson05;

import pers.ylw.lesson05.utils.JdbcUtils_DBCP;

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

public class TestDBCP {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;

        try {
            conn = JdbcUtils_DBCP.getConnection(); //只是改了這一行和最後關閉資源的時候,使用的類,其他的和前面的筆記沒有區別

            //注意PreparedStatement與Statement的區別
            //書寫SQL語句,使用?佔位符代替參數
            String sql = "insert into users(`id`,`NAME`,`PASSWORD`,`email`,`birthday`) values (?,?,?,?,?)";
            st = conn.prepareStatement(sql);//預編譯sql,先寫sql,然後不執行
            //手動給參數賦值,第一個參數是?的下標(從1開始),第二個參數是?的值
            st.setInt(1,4);
            st.setString(2,"ylw");
            st.setString(3,"123456");
            st.setString(4,"[email protected]");
            //注意時間轉換,sql.Date數據庫時間,util.Date Java時間,new Date().getTime()獲得時間戳
            st.setDate(5,new java.sql.Date(new Date().getTime()));
            //執行
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("插入成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils_DBCP.release(conn,st,null); //關資源
        }
    }
}

如果你使用的包版本比較新可能會出現異常:
用DBCP進行數據連接池連接的時候出現java.lang.NoClassDefFoundError: Could not initialize class xxx.xxx.util.JdbcUtils_DBCP異常
解決方案:導入commanns-logging包
下載地址 https://commons.apache.org/proper/commons-logging/download_logging.cgi
在這裏插入圖片描述

C3P0

需要用到的jar包

1.c3p0 下載地址 https://sourceforge.net/projects/c3p0/
點擊下載,你得等一會他才下載
在這裏插入圖片描述
包在lib文件夾裏
在這裏插入圖片描述
在這裏插入圖片描述
2.mchange-commons-java
下載地址 https://mvnrepository.com/artifact/com.mchange/mchange-commons-java
推薦倒數第二新版本
在這裏插入圖片描述
點擊jar進行下載
在這裏插入圖片描述
導包在上面DBCP中講的很詳細了

代碼相關

在src下新建一個c3p0的配置文件c3p0-config.xml(新建File,命名加後綴爲就行)

<?xml version="1.0" encoding="UTF-8" ?>
<c3p0-config>
    <!--c3p0的缺省(默認)配置
    如果在代碼中"ComboPooledDataSource ds = new ComboPooledDataSource();"這樣寫就表示使用的是C3P0的缺省(默認)配置
    -->
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <!--改成你自己的url-->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false</property>
        <!--改成你自己的用戶名-->
        <property name="user">root</property>
        <!--改成你自己的密碼-->
        <property name="password">123456</property>

        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </default-config>

    <!--
    C3P0的命名配置,
    如果在代碼中"ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");"這樣寫就表示使用的是name是MySQL
    -->
    <named-config name="MySQL">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <!--改成你自己的url-->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false</property>
        <!--改成你自己的用戶名-->
        <property name="user">root</property>
        <!--改成你自己的密碼-->
        <property name="password">123456</property>

        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </named-config>

</c3p0-config>

自己封裝一個工具類 JdbcUtils_C3P0

package pers.ylw.lesson05.utils;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JdbcUtils_C3P0 {

    private static ComboPooledDataSource dataSource = null;

    static {
        try{
            //代碼版配置,不寫在配置文件裏
//            dataSource = new ComboPooledDataSource();
//            dataSource.setDriverClass();
//            dataSource.setUser();
//            dataSource.setPassword();
//            dataSource.setJdbcUrl();
//
//            dataSource.setMaxPoolSize();
//            dataSource.setMinPoolSize();

            //c3p0的配置文件不需要向DBCP那樣獲取,可以自動加載
            //創建數據源 工廠模式-->創建對象
            dataSource = new ComboPooledDataSource("MySQL");//配置文件寫法

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //獲取連接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection(); //從數據源中獲取連接
    }

    //釋放連接資源
    public static void release(Connection conn, Statement st,ResultSet rs){
        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

使用這個 JdbcUtils_C3P0 工具類進行操作

package pers.ylw.lesson05;

import pers.ylw.lesson05.utils.JdbcUtils_C3P0;
import pers.ylw.lesson05.utils.JdbcUtils_DBCP;

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

public class TestC3P0 {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;

        try {
            conn = JdbcUtils_C3P0.getConnection(); //只是改了這一行和最後關閉資源的時候,使用的類,其他的前面的筆記沒有區別

            //注意PreparedStatement與Statement的區別
            //書寫SQL語句,使用?佔位符代替參數
            String sql = "insert into users(`id`,`NAME`,`PASSWORD`,`email`,`birthday`) values (?,?,?,?,?)";
            st = conn.prepareStatement(sql);//預編譯sql,先寫sql,然後不執行
            //手動給參數賦值,第一個參數是?的下標(從1開始),第二個參數是?的值
            st.setInt(1,4);
            st.setString(2,"ylw");
            st.setString(3,"123456");
            st.setString(4,"[email protected]");
            //注意時間轉換,sql.Date數據庫時間,util.Date Java時間,new Date().getTime()獲得時間戳
            st.setDate(5,new java.sql.Date(new Date().getTime()));
            //執行
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("插入成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils_C3P0.release(conn,st,null); //關資源
        }
    }
}

C3P0運行成功還會顯示配置文件
在這裏插入圖片描述

總結

無論使用什麼數據,本質還是一樣的,DateSource接口不會變,方法就不會變

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章