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

1 鏈接池概述

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

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


通過上面的介紹,咱們須要建立一個鏈接池,以供咱們鏈接數據庫操做,在沒用鏈接池以前,用戶訪問數據庫的時候都是本身建立鏈接對象的。
druid的使用詳情,還不快來看看?mysql

咱們使用了鏈接池以後:從系統開始啓動的時候就會建立一個工廠對象,裏面有必定數量的數據庫鏈接對象,用戶使用的時候直接會從池子裏拿鏈接對象,不須要本身在建立了。
druid的使用詳情,還不快來看看?git

鏈接池解決現狀問題的原理github

Connection鏈接對象 操做特色
建立時 鏈接對象再也不由本身建立,而是系統啓動的時候已經建立必定數量的鏈接, 而且放在鏈接池中
使用時 直接從鏈接池中去獲取一個已經建立好的鏈接對象便可
關閉時 不是真的關閉鏈接對象,而是將鏈接對象再放回到鏈接池中,供下一個用戶使用
  1. 數據源接口:javax.sql.DataSource接口

數據源接口中的方法:sql

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

每一個鏈接池都會有不少的參數,每一個參數都有不一樣的含義,幾乎全部的參數都是由默認值的,參數名在不一樣的鏈接池中表明的意思也有所差別!數據庫

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

2 經常使用的鏈接池(咱們首選druid)

經常使用鏈接池的介紹

DataSource自己是Oracle公司提供的一個接口,自己沒有具體的實現,它的實現由各大鏈接池的數據庫廠商去實現,咱們只須要學習如何使用就ok了。服務器

經常使用的鏈接池組件:ide

  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. 修改了獲取鏈接的方法,從鏈接池中獲取鏈接對象
相關文章
相關標籤/搜索