druid的使用詳情,還不快來看看?

1 連接池概述

  • 連接對象的使用問題
    我們原先連接數據庫都是用一次創建連接一次,不用的話就直接關閉了,然後在使用在創建,這樣就造成了佔用資源過多加重服務器負擔,耗時。
  • 解決
    解決這些問題,我們要考慮如何提高連接速度,還有就是如何提高使用率。

下面會詳細介紹一種最實用的數據庫連接池的詳細介紹及其使用------德魯伊(druid)


經過上面的介紹,我們需要創建一個連接池,以供我們連接數據庫操作,在沒用連接池之前,用戶訪問數據庫的時候都是自己創建連接對象的。
druid的使用詳情,還不快來看看?

我們使用了連接池之後:從系統開始啓動的時候就會創建一個工廠對象,裏面有一定數量的數據庫連接對象,用戶使用的時候直接會從池子裏拿連接對象,不需要自己在創建了。
druid的使用詳情,還不快來看看?

連接池解決現狀問題的原理

Connection連接對象 操作特點
創建時 連接對象不再由自己創建,而是系統啓動的時候已經創建一定數量的連接, 並且放在連接池中
使用時 直接從連接池中去獲取一個已經創建好的連接對象即可
關閉時 不是真的關閉連接對象,而是將連接對象再放回到連接池中,供下一個用戶使用
  1. 數據源接口:javax.sql.DataSource接口

數據源接口中的方法:

DataSource接口中的方法 描述
Connection getConnection() 從連接池中獲取連接對象

每個連接池都會有很多的參數,每個參數都有不同的含義,幾乎所有的參數都是由默認值的,參數名在不同的連接池中代表的意思也有所差異!

常用參數 描述
初始連接數 服務器啓動的時候創建的連接對象數量
最大連接數 連接池中最多可以允許放多少個連接對象
最長等待時間 如果連接池中沒有連接對象,設置用戶等待的最長時間是多久,單位是毫秒。 如果超過這個時間就拋出異常
最長空閒回收時間 如果一個連接對象長時間沒有人使用,設置多久回收這個對象,默認是不回收。

2 常用的連接池(我們首選druid)

常用連接池的介紹

DataSource本身是Oracle公司提供的一個接口,本身沒有具體的實現,它的實現由各大連接池的數據庫廠商去實現,我們只需要學習如何使用就ok了。

常用的連接池組件:

  1. 阿里巴巴-德魯伊druid連接池:Druid是阿里巴巴開源平臺上的一個項目(主要)。
  2. DBCP(DataBase Connection Pool)數據庫連接池,是Apache上的一個Java連接池項目,也是Tomcat使用的連接池組件。
  3. C3P0是一個開源的JDBC連接池,目前使用它的開源項目有Hibernate,Spring等。C3P0有自動回收空閒連接功能。

使用Druid連接池

DRUID簡介

Druid是阿里巴巴開發的號稱爲監控而生的數據庫連接池,在功能、性能、擴展性方面,都超過其他數據庫連接池。Druid已經在阿里巴巴部署了超過600個應用,經過一年多生產環境大規模部署的嚴苛考驗。如:一年一度的雙十一活動,每年春運的搶火車票。

Druid的下載地址:https://github.com/alibaba/druid

DRUID連接池使用的jar包:druid-1.0.9.jar

常用的配置參數

參數 說明
url 連接字符串
username 用戶名
password 密碼
driverClassName 驅動類名,會自動根據URL識別,這一項可以不配置
initialSize 初始連接數
maxActive 最大連接數
maxWait 最長等待時間

Druid連接池API介紹

  1. 得到配置文件的輸入流
Class類中的方法 說明
InputStream getResourceAsStream(String path) 加載類路徑下配置文件,轉成一個輸入流對象
  1. Properties類的方法,讀取屬性文件中的鍵和值,並且加載到集合中
    druid的使用詳情,還不快來看看?
  2. 通過Druid工廠的靜態方法創建連接池,提供屬性集合作爲參數
DruidDataSourceFactory的方法 方法
public static DataSource createDataSource(Properties properties) 通過屬性集合中屬性,創建一個連接池

3 使用Druid連接池

案例演示:獲取連接對象

導包:
druid的使用詳情,還不快來看看?

步驟

  1. 在src目錄下創建一個properties文件,文件名隨意,設置上面的參數
  2. Java代碼
    1. 加載properties文件的內容到Properties對象中
    2. 使用工廠類,創建DRUID連接池,使用配置文件中的參數
    3. 從DRUID連接池中取出10個連接輸出

druid的使用詳情,還不快來看看?

.properties配置文件:

url=jdbc:mysql://localhost:3306/test
username=root
password=root
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
maxWait=2000

java代碼:

public class Demo2Druid {

    public static void main(String[] args) throws Exception {
        //1.從類路徑下加載配置文件,獲取一個輸入流。如果不指定路徑,默認是讀取同一個包下資源文件
        InputStream inputStream = Demo2Druid.class.getResourceAsStream("/druid.properties");
        //2.使用Properties對象的方法將配置文件中屬性加載到Properties對象中
        Properties properties = new Properties();
        //加載了配置文件中所有的屬性
        properties.load(inputStream);
        //3.通過druid的工廠類創建連接池
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

        //獲取10個連接對象
        for (int i = 1; i <= 11; i++) {
            Connection connection = dataSource.getConnection();
            System.out.println("第" + i + "個連接對象:" + connection);
            //第3個連接關閉
            if (i==3) {
                connection.close();
            }
        }
    }
}

druid的使用詳情,還不快來看看?
但是如果超過了數據庫最大連接數量:
druid的使用詳情,還不快來看看?
但是我們讓第三個關閉了連接,相當於還給連接池一個連接對象,所以會打印是以個結果:(有兩個地址值是相同的!)
druid的使用詳情,還不快來看看?



4 數據工具類再增強

分析

使用Druid連接池來獲取連接對象,達到提升訪問數據庫速度目的

  1. 去掉類中與數據庫連接有關的代碼
  2. 得到數據庫的連接,從連接池中獲取
  3. 新加一個方法,獲取連接池對象
  4. 在類一開始加載就能夠獲取連接池(數據源)對象,在靜態代碼塊中創建連接池

代碼

package com.aoshen.Test;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class JDBCUtils {
    //聲明連接池對象
    private static DataSource dataSource;

    //使用靜態,是類加載的時候就創建連接池
    static{
        try {
            //讀取配置文件
            InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("druid");
            //獲取Properties對象,加載到該對象中
            Properties properties = new Properties();
            //獲取配置文件
            properties.load(inputStream);
            //創建druid工廠
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

    /**
     * 關閉連接
     * 查詢調用這個方法
     */
    public static void close(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (statement != null) {
                statement.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 關閉連接
     * 增刪改沒有結果集
     */
    public static void close(Connection connection, Statement statement) {
        //直接調用上面的方法
        close(connection, statement, null);
    }

    /**
     * 通用的增刪改方法
     */
    public static int update(String sql,Object...args){
        Connection conn = null;
        PreparedStatement ps = null;
        //返回影響的行數
        int row = 0;
        try{
            //獲取連接
            conn = getConn();
            //獲取預編譯對象
            ps = conn.prepareStatement(sql);
            //獲取元數據,得到有多少佔位符
            ParameterMetaData metaData = ps.getParameterMetaData();
            int count = metaData.getParameterCount();
            //循環獲取賦值
            for (int i = 0; i < count; i++) {
                ps.setObject(i+1,args[i]);
            }
            //執行SQL語句
            row = ps.executeUpdate();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            close(conn,ps);
        }
        return row;
    }

    /**
     * 通用的查詢方法
     */
    public static <T> List<T> equery(String sql,Class<T>c,Object...args){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        //創建集合用於接收數據庫中查的值
        List<T>list = new ArrayList<>();
        try{
            //獲取連接
            conn = getConn();
            //獲取預編譯對象
            ps = conn.prepareStatement(sql);
            //通過獲取元數據給佔位符賦值
            ParameterMetaData metaData = ps.getParameterMetaData();
            int count = metaData.getParameterCount();
            for (int i = 0; i < count; i++) {
                ps.setObject(i+1,args[i]);
            }
            //執行sql
            rs = ps.executeQuery();
            //遍歷集合,封裝到集合中嗎,一行數據封裝一個對象
            while (rs.next()){
                //每條記錄封裝成一個對象
                T t = c.newInstance();
                //得到實體類中有哪些列名
                Field[] fields = c.getDeclaredFields();
                //遍歷賦值
                for (Field field : fields) {
                    //獲取列名
                    String name = field.getName();
                    //獲取內容
                    Object value = rs.getObject(name);
                    //因爲是私有的,要暴力反射
                    field.setAccessible(true);
                    //把最後得到的值賦值給創建的對象中
                    field.set(t,value);
                }
                //把最後含每一行值的對象添加到集合中
                list.add(t);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            close(conn,ps,rs);
        }
        return list;
    }

}

使用工具類

/**
 * 使用工具類
 */
public class Demo3UseUtils {

    public static void main(String[] args) {
        //使用工具類添加1條記錄
        int row = JdbcUtils.update("insert into student values(null,?,?,?)", "嫦娥", 0, "1997-07-07");
        System.out.println("添加了" + row + "條");

        //使用工具類查詢所有的數據
        List<Student> students = JdbcUtils.query("select * from student", Student.class);
        //打印
        students.forEach(System.out::println);
    }

}

druid的使用詳情,還不快來看看?

小結

修改了連接的獲取方式

  1. 在靜態代碼塊中創建連接池對象
  2. 添加了獲取數據源的方法
  3. 修改了獲取連接的方法,從連接池中獲取連接對象
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章