当前位置: 首页 > 数据库 > MySQL教程 >正文

druid的使用详情,还不快来看看?

来源:互联网时间:2021-01-13 15:35:59编辑:网友分享
1 连接池概述 连接对象的使用问题:我们原先连接数据库都是用一次创建连接一次,不用的话就直接关闭了,然后在使用在创建,这样就造成了占用资源过多加重服务器负担,

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. 修改了获取连接的方法,从连接池中获取连接对象

上一篇: MySQL数据类型全解析

下一篇:年底了,你的mysql密码安全吗

您可能感兴趣的文章

相关阅读