14.數(shù)據(jù)庫(kù)連接池【C3P0俩垃、阿里Druid励幼、Spring JDBC】

數(shù)據(jù)庫(kù)連接池

概念: 一個(gè)容器(集合),存放數(shù)據(jù)庫(kù)連接的容器口柳。當(dāng)系統(tǒng)初始化好后苹粟,容器被創(chuàng)建,容器中會(huì)申請(qǐng)一些連接對(duì)象跃闹,當(dāng)用戶來訪問數(shù)據(jù)庫(kù)時(shí)嵌削,從容器中獲取連接對(duì)象毛好,當(dāng)用戶訪問完之后,會(huì)將連接對(duì)象歸還給容器苛秕。

好處:

  1. 節(jié)約資源
  2. 用戶訪問高效

技術(shù)支持:

  1. C3P0:數(shù)據(jù)庫(kù)連接池技術(shù)
  2. Druid:【很牛逼】數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)技術(shù)肌访,阿里巴巴提供

一、標(biāo)準(zhǔn)接口【javax.sql.DataSource】【具體實(shí)現(xiàn)由數(shù)據(jù)庫(kù)廠商去完成】

javax.sql.DataSource接口中的方法:

  • Connection getConnection():獲取連接
  • Connection.close():如果連接對(duì)象Connection是從連接池中獲取的艇劫,那么調(diào)用Connection.close()方法吼驶,則不再會(huì)關(guān)閉連接了。

二店煞、C3P0數(shù)據(jù)庫(kù)連接池技術(shù)

1.使用步驟

  1. 導(dǎo)包jar:
    • 數(shù)據(jù)庫(kù)驅(qū)動(dòng)包【前提】
    • c3p0-0.9.5.2.jar
    • mchange-commons-java-0.2.12.jar
  2. 定義配置文件
    • 名稱:c3p0.properties 或者 c3p0-config.xml
    • 路徑:src目錄下
  3. 創(chuàng)建核心對(duì)象 數(shù)據(jù)庫(kù)連接池對(duì)象 ComboPooledDataSource
  4. 獲取連接:getConnection(),執(zhí)行業(yè)務(wù)邏輯
  5. 歸還連接:Connection.close()

2.代碼實(shí)現(xiàn)

// 對(duì)應(yīng)的包
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

# ---------------------------------------- #

// 1.創(chuàng)建數(shù)據(jù)庫(kù)連接池對(duì)象【使用默認(rèn)配置蟹演,傳入?yún)?shù)則使用對(duì)應(yīng)的配置】
DataSource ds = new ComboPooledDataSource();

// 2.獲取連接對(duì)象
Connection conn = ds.getConnection();

// 3.業(yè)務(wù)邏輯
String sql = "create table student(" +
        "id int primary key auto_increment," +
        "name varchar(10)," +
        "age int," +
        "gender char(3)," +
        "birthday Date)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.executeUpdate();
ps.close();

// 4. 歸還連接對(duì)象
conn.close();

四、Druid數(shù)據(jù)庫(kù)連接池技術(shù)顷蟀,【阿里巴巴提供】

1.使用步驟

  1. 導(dǎo)入 druid-1.0.9.jar 包【也得導(dǎo)入數(shù)據(jù)庫(kù)驅(qū)動(dòng)包】
  2. 定義配置文件
    • 可以是 properties 形式
    • 可以叫任意名稱酒请,可以放在任意目錄下
  3. 加載配置文件:推薦 properties
  4. 獲取數(shù)據(jù)庫(kù)連接池對(duì)象:通過工廠類來獲取
    • DruidDataSourceFactory
  5. 獲取連接: getConnection

2. 代碼實(shí)現(xiàn)

import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

public class DruidLearn {

    public static void main(String[] args) throws Exception {
        // 1.加載配置文件
        Properties pro = new Properties();
        InputStream in = DruidLearn.class
                         .getClassLoader()
                         .getResourceAsStream("druid.properties");
        pro.load(in);

        // 2.獲取連接池對(duì)象
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);

        // 3.獲取連接
        Connection conn = ds.getConnection();

        // 4.執(zhí)行力業(yè)務(wù)邏輯
        String sql1 = "create table user(id int primary key auto_increment,name varchar(10),password varchar(16))";
        PreparedStatement ps = conn.prepareStatement(sql1);
        int res = ps.executeUpdate();
        String sql2 = "insert into user values(null,'曉慶','abc123'),(null,'小竹','123abc')";
        ps = conn.prepareStatement(sql2);
        int res2 = ps.executeUpdate();
        String sql3 = "select * from user";
        ps = conn.prepareStatement(sql3);
        ResultSet rs = ps.executeQuery();
        while (rs.next()) { int id = rs.getInt("id");String name = rs.getString("name");String password = rs.getString("password");System.out.println("編號(hào):" + id + " 姓名:" + name + " 密碼:" + password); }

        // 5.釋放資源
        rs.close();
        ps.close();
        // 6.歸還資源
        conn.close();
    }
}

五、封裝一個(gè)Druid工具類JDBCUtils

  1. 提供靜態(tài)代碼塊加載排至文件衩椒,初始化連接池對(duì)象
  2. 提供的方法:
    • 獲取連接池的方法
    • 通過數(shù)據(jù)庫(kù)連接池獲取連接
    • 釋放資源
package JDBCUtils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtils {
    /**
     * 1.定義成員變量 DateSource 連接池
     */
    private static DataSource ds;

    /**
     * 2.加載配置文件
     */
    static {
        try{
            Properties pro = new Properties();
            pro.load(JDBCUtils.class.getClassLoader()
                    .getResourceAsStream("druid.properties"));

            // 根據(jù)工廠類獲取數(shù)據(jù)庫(kù)連接池對(duì)象 SataSource
            ds = DruidDataSourceFactory.createDataSource(pro);

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

    /**
     * 獲取連接池
     */
    public static DataSource getDataSource() {
        return ds;
    }

    /**
     * 獲取連接
     */
    public static Connection getConnection() {
        try { return ds.getConnection(); } catch (Exception e) { e.printStackTrace();return null; }
    }

    /**
     * 釋放資源
     */

    public static void close(Statement stmt, Connection conn) {
        if(stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } }
        if(conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } }
    }

    /**
     * 釋放資源蚌父; 重載
     */
    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        if(rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } }
        close(stmt, conn);
    }
}

六、Spring JDBC

Spring 框架對(duì)JDBC的簡(jiǎn)單封裝毛萌,提供了一個(gè)JdbcTemplate對(duì)象簡(jiǎn)化JDBC的開發(fā)

1.操作步驟【使用上方實(shí)現(xiàn)的JDBCUtils工具箱類】

  1. 導(dǎo)入jar包苟弛,例如:
    • commons-logging-1.2.jar;
    • spring-beans-5.0.0.RELEASE.jar;
    • spring-core-5.0.0.RELEASE.jar;
    • spring-jdbc-5.0.0.RELEASE.jar;
    • spring-tx-5.0.0.RELEASE.jar;
  2. 創(chuàng)建JdbcTemplate對(duì)象。依賴于數(shù)據(jù)源 DataSource【從JDBCUtils獲得】
    • JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource())
  3. 調(diào)用JdbcTemplate的方法來完成CRUD的操作

2.JdbcTemplate類中的方法

  1. int update(String sql, ...): 執(zhí)行DML語(yǔ)句阁将,增膏秫、刪、改語(yǔ)句做盅。
  2. Map<String,Object> QueryForMap(String sql, ...): 查詢結(jié)果將結(jié)果集封裝成map集合缤削,將列名作為key,將值作為value,將這條記錄封裝為一個(gè)map集合。
    • 注意:此方法查詢的結(jié)果集長(zhǎng)度只能是【1】吹榴,也就是只能是一條記錄亭敢。
  3. List<Map<String,Object>> queryForList(String sql, ...): 查詢結(jié)果將結(jié)果集封裝為list集合
    • 注意:將每一條記錄封裝為一個(gè)Map集合,再將Map集合在到List集合中
  4. List<?> query(String sql, RowMapper<?> rm):查詢結(jié)果图筹,將結(jié)果封裝為JavaBean對(duì)象帅刀。
    • 參數(shù):RowMapper接口:一般使用 BeanPropertyRowMapper實(shí)現(xiàn)類。當(dāng)然可以重寫內(nèi)部的mapRow抽象方法.完成數(shù)據(jù)到JavaBean的自動(dòng)封裝

    new BeanPropertyMapper<E>(E.class):【E必須是JavaBean規(guī)范類远剩,內(nèi)部的反射機(jī)制才好工作扣溺!

  5. E queryForObject(String sql, E.class): 查詢結(jié)果,將結(jié)果封裝為對(duì)象,一般為基本數(shù)據(jù)類型對(duì)象瓜晤。
    • 注意: 一般用于聚合函數(shù)的查詢

使用JdbcTemplate中的方法锥余,得到JdbcTemplate對(duì)象后,直接進(jìn)行SQL操作痢掠,不需要任何額外申請(qǐng)資源或者釋放資源的操作驱犹!資源用完了就釋放嘲恍,結(jié)果集也是Map,List或者基本數(shù)據(jù)類型的包裝類

3.案例展示

代碼中使用JDBCUtils工具類是上面所描述的,Student類包含屬性【int id,String name,int age,String gender】,JavaBean規(guī)范類着绷,代碼略蛔钙!

package jdbcTemplate;

import JDBCUtils.JDBCUtils;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

public class JDBCTemplate {

    // 獲取JDBCTemplate對(duì)象
    private static JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());

    // 創(chuàng)建一張表格
    public static void create() {
        String sql = "create table student(" +
                "id int primary key auto_increment," +
                "name varchar(10)," +
                "age int," +
                "gender varchar(6))";
        int count = template.update(sql);
        System.out.println(count);
    }

    // 添加一些記錄
    public static void insert() {
        String sql = "insert into student values " +
                "(null,?,?,?)," +
                "(null,?,?,?);";
        int count = template.update(sql, "曉慶",18,"女","洪祥",20,"男");
        System.out.println(count);
    }

    // 修改記錄
    public static void update() {
        String sql = "update student set age = ? where name = ?";
        int res = template.update(sql, 22, "小竹");
        System.out.println(res);
    }

    // 刪除一些記錄
    public static void delect() {
        String sql = "delete from student where name in (?, ?)";
        int res = template.update(sql,"曉慶", "洪祥");
        System.out.println(res);
    }

    /**
     * 查詢操作
     */
    // queryForMap - 查詢的結(jié)果記錄值允許一條!
    public static void queryForMap() {
        String sql = "select * from student where name=?";
        Map<String, Object> map = template.queryForMap(sql, "曉慶");
        System.out.println(map);
    }

    // 5.查詢所有記錄荠医,將其封裝為L(zhǎng)ist
    public static void queryForList() {
        String sql = "select * from student";
        List<Map<String, Object>> list = template.queryForList(sql);
        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }

    // 6.查詢所有記錄吁脱,將其封裝為Student對(duì)象的List集合【接口方法重寫】
    public static void queryOne() {
        String sql = "select * from student";
        List<Student> list = template.query(sql,new RowMapper<Student>() {

            /**
             * mapRow的返回值是一個(gè)對(duì)象而不是List集合,
             * 說明參數(shù)ResultSet是遍歷查詢的每個(gè)結(jié)果
             * */
            @Override
            public Student mapRow(ResultSet rs, int i) throws SQLException {
                Student student = new Student();
                student.setId(rs.getInt("id"));
                student.setName(rs.getString("name"));
                student.setAge(rs.getInt("age"));
                student.setGender(rs.getString("gender"));
                return student;
            }
        });

        for (Student student : list) {
            System.out.println(student);
        }
    }

    // 7.查詢所有記錄彬向,將其封裝為Student對(duì)象的List集合
    public static void queryTwo() {
        String sql = "select * from student;";
        List<Student> list = template.query(sql, new BeanPropertyRowMapper<>(Student.class));
        for (Student student : list) {
            System.out.println(student);
        }
    }


    // 8.查詢總記錄數(shù)
    public static void queryAgg() {
        String sql = "select count(*) number from student";
        Long total = template.queryForObject(sql,Long.class);
        System.out.println(total);
    }

    public static void main(String[] args) {
        // create();
        // insert();
        // update();
        // delect();

        /*查詢操作兼贡!*/
        // queryForMap();
        // queryForList();
        // queryOne();
        // queryTwo();
        // queryAgg();

    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市娃胆,隨后出現(xiàn)的幾起案子遍希,更是在濱河造成了極大的恐慌,老刑警劉巖里烦,帶你破解...
    沈念sama閱讀 222,946評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凿蒜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡胁黑,警方通過查閱死者的電腦和手機(jī)废封,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丧蘸,“玉大人漂洋,你說我怎么就攤上這事×ε纾” “怎么了刽漂?”我有些...
    開封第一講書人閱讀 169,716評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)弟孟。 經(jīng)常有香客問我贝咙,道長(zhǎng),這世上最難降的妖魔是什么拂募? 我笑而不...
    開封第一講書人閱讀 60,222評(píng)論 1 300
  • 正文 為了忘掉前任颈畸,我火速辦了婚禮,結(jié)果婚禮上没讲,老公的妹妹穿的比我還像新娘。我一直安慰自己礁苗,他們只是感情好爬凑,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著试伙,像睡著了一般嘁信。 火紅的嫁衣襯著肌膚如雪于样。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,807評(píng)論 1 314
  • 那天潘靖,我揣著相機(jī)與錄音穿剖,去河邊找鬼。 笑死卦溢,一個(gè)胖子當(dāng)著我的面吹牛糊余,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播单寂,決...
    沈念sama閱讀 41,235評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼贬芥,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了宣决?” 一聲冷哼從身側(cè)響起蘸劈,我...
    開封第一講書人閱讀 40,189評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎尊沸,沒想到半個(gè)月后威沫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,712評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡洼专,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評(píng)論 3 343
  • 正文 我和宋清朗相戀三年棒掠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壶熏。...
    茶點(diǎn)故事閱讀 40,926評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡句柠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出棒假,到底是詐尸還是另有隱情溯职,我是刑警寧澤,帶...
    沈念sama閱讀 36,580評(píng)論 5 351
  • 正文 年R本政府宣布帽哑,位于F島的核電站谜酒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏妻枕。R本人自食惡果不足惜僻族,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望屡谐。 院中可真熱鬧述么,春花似錦、人聲如沸愕掏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)饵撑。三九已至剑梳,卻和暖如春唆貌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背垢乙。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工锨咙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人追逮。 一個(gè)月前我還...
    沈念sama閱讀 49,368評(píng)論 3 379
  • 正文 我出身青樓酪刀,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親羊壹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蓖宦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容