Druid数据库连接池读取properties文件

1.Druid的简单介绍

Druid(德鲁伊)是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。
官网:https://github.com/alibaba/druid(访问比较慢,所以你懂的)
在这里插入图片描述
要使用Druid连接池,首先把jar包导入项目,通过druid.properties配置文件进行配置。(配置文件名称自定义不是非得叫druid的)

  1. 普通的项目,没有使用maven进行管理的,需要自己去导入jar包;
    在这里插入图片描述
  2. maven项目工程,直接在pom.xml中进行配置
    在这里插入图片描述

Java 中的 properties 文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件。

  1. 文件的内容是格式是 “键=值”(key-value) 的格式。
  2. 在 properties 文件中,可以用"#" 来作注释。

properties文件在Java编程中用到的地方很多,操作很方便。
介于此,我们可以把数据库连接信息,如驱动、URL、账号、密码等这些动态信息不必写在class中,而放入一个可读取的配置的属性文件中,程序从属性文件中读取值以实现"运行时动态加载"。

常用的参数如下:https://github.com/alibaba/druid/wiki/DruidDataSource配置属性列表
在这里插入图片描述

DruidDataSource支持哪些数据库:(理论上说,支持所有有jdbc驱动的数据库。实际测试过的有)
在这里插入图片描述

2.使用举例

当然,在连接数据库时,我们也是要导入对应的驱动jar包的,
这里默认大家都已经导入,咱们只是探讨连接库时的写法
http://ftp.jaist.ac.jp/pub/mysql/Downloads/Connector-J/
例如:
在这里插入图片描述

2.1 正常不使用数据库连接池操作数据库

在不使用这些第三方的工具jar包时,我们连接数据库,可能是这样子的(以mysql为例啊)

//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//要连接的数据库的url(地址),不同的数据库,写法不一样
String url = "jdbc:mysql://localhost:3306/jdbc_db";
//你登录的用户名
String user = "用户名";
//你登录的密码
String password = "密码";
//获取一个连接 conn
Connection conn =DriverManager.getConnection(url, user, password);

完整举例:

import java.sql.*;

/**
 * @author hyl
 * @version 1.0
 * @date 2022/12/3-15:39
 */

public class java02 {
    public static void main(String[] args) {
        Connection conn=null;
        ResultSet resultSet=null;
        Statement statement=null;
        try {
            //注册驱动
            //说明一下,这里我的是8版本所以要加上cj,5版本的不加
            Class.forName("com.mysql.cj.jdbc.Driver");
            //要连接的数据库的url(地址),不同的数据库,写法不一样
            String url = "jdbc:mysql://localhost:3307/sms";
            //你登录的用户名
            String user = "root";
            //你登录的密码
            String password = "123456";
            //获取一个连接 conn
             conn= DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            statement= conn.createStatement();
            resultSet= statement.executeQuery("select * from user");
            while (resultSet.next()){
                //可以通过索引,也可以通过对应的名称
                System.out.println("方式一通过索引:"+resultSet.getString(1)+" "+resultSet.getString(2)
                        +" "+resultSet.getString(3));
                /*System.out.println("方式二通过名称"+resultSet.getString("Sno")+" "+resultSet.getString("username")
                        +" "+resultSet.getString("password"));*/
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            // 释放资源
            try {
                if (conn!=null){
                    conn.close();
                }
                if(statement!=null){
                    statement.close();
                }
                if(resultSet!=null){
                    resultSet.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }

        }
    }
}

查询一下user表,并打印输出里面的内容:
在这里插入图片描述
在这里插入图片描述

我们可以看到,传统的写法是很麻烦的,每次需要操作数据库,都要写一大堆的连接“配置”,而且每次连接的获取与释放都是要耗费电脑资源的,很不方便。

2.1使用数据库连接池

好处:

  1. 资源重用
    由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数量)。
  2. 更快的系统响应速度
    数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。
  3. 新的资源分配手段
    对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接池技术,几年钱也许还是个新鲜话题,对于目前的业务系统而言,如果设计中还没有考虑到连接池的应用。某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。
  4. 统一的连接管理,避免数据库连接泄漏
    在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用连接。从而避免了常规数据库连接操作中可能出现的资源泄漏。

在说连接池的使用前,我们先说下Properties类与Properties配置文件

  1. Properties类与Properties配置文件
    Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存属性集。不过Properties有特殊的地方,就是它的键和值都是字符串类型。
  2. Properties中的主要方法
    (1)load(InputStream inStream)
    这个方法可以从.properties属性文件对应的文件输入流中,加载属性列表到Properties类对象。如下面的代码:
    在这里插入图片描述
    (2)store(OutputStream out, String comments)
    这个方法将Properties类对象的属性列表保存到输出流中。如下面的代码:
    在这里插入图片描述
    如果comments不为空,保存后的属性文件第一行会是#comments,表示注释信息;如果为空则没有注释信息。注释信息后面是属性文件的当前保存时间信息。
    (3)getProperty/setProperty
    这两个方法是分别是获取和设置属性信息。

使用配置文件的时候,只是把这些内容放到了druid.properties文件中(名字自定义,习惯使用druid)。
druid.properties(放到资源目录下)

#==============正常配置=============
#key=value 注释说明是以该种形式写入文件的
# 指明驱动(数据库的类别,可写可不写,不写会根据url自动匹配)

driverClassName=com.mysql.cj.jdbc.Driver

# 指明要操作的数据库url
# localhost指的是本地ip(127.0.0.1)也就是要访问的是本地的数据库
#3006是对应的端口号,mysql默认是3306,根据需求,端口号可能会改变
# sms就是你要操作的数据库中的具体的那个库,当然也可以具体到表
#?rewriteBatchedStatements=true 可要可不要,作用是是否允许批处理
#如果操作的是本地数据库,且端口号不变,可以简写为:url=jdbc:mysql:///sms

url=jdbc:mysql://localhost:3306/sms?rewriteBatchedStatements=true

# 登录数据库的用户名
username=root
# 登录数据库的密码
password=123456

#=========下面是数据库连接池的配置=====
#initial connection Size 初始化连接数10个
initialSize=10
#min idle connecton size 最小连接数5个
minIdle=5
#max active connection size 最大连接数50个
maxActive=50
#max wait .time (5000 mil seconds) 
#最大等待时间5s,就是有新的请求索要连接时,如果池子里面没有可用连接了,
#我最多等待5s,5s的时间还没拿到,就放弃本次的索求
maxWait=5000

采用类加载器ClassLoader得到指定文件名properties文件的的输入流,进而用DruidDataSourceFactory的createDataSource方法获取连接池对象

浅看一下DruidDataSourceFactory.createDataSource()的源码:他会自动的去读取我们写的配置文件,并进行对应的设置,因此在写配置文件时,像url,driverClassName这些key的时候一定要与之对应,不能乱写
在这里插入图片描述

JDBCUtil.java

package com.hyl.sams.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileReader;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
 * 德鲁伊连接池工具类
 * 连接池工具类,连接数据库
 * @author hyl
 */

public class JDBCUtil {
    private static DataSource source;
    //初始化连接
    static {
        Properties properties = new Properties();
        try {
            //使用ClassLoader加载配置文件,获取字节输入流
            InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("druid.properties");
            properties.load(is);
            source = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接
    public static Connection getConnection() throws SQLException {
        return source.getConnection();
    }

    /**
     * 释放连接(不是断掉连接,而是归还释放)
     * @param resultSet
     * @param statement
     * @param connection
     */
    public static void Close(ResultSet resultSet, Statement statement, Connection connection){
        try {
            if (resultSet!=null) {
                resultSet.close();
            }
            if (statement!=null) {
                statement.close();
            }
            if (connection!=null) {
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}


上述代码,只需通过JDBCUtil.getConnection()就可以从池子里面获取一个连接,也只是方便我们去获取数据库的连接,但是当我们要去操作数据库的时候,还不是很方便,这里我们去借助第三方的数据库工具jar包,去简化我们的sql操作。
在这里插入图片描述
BasicDao.java

package com.hyl.sams.dao;

import com.hyl.sams.utils.Jdbc_Druid_Utils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
 * @author hyl
 */
public class BasicDao {
    private QueryRunner qr=new QueryRunner();

    //统一说明:Object... parameters
    // 是动态传参,参数个数0-n

    /**
     *  插入、更新或删除
     * @param sql
     * @param parameters
     * @return
     */
    public int update(String sql,Object... parameters){
        Connection connection=null;
        try {
            connection= JDBCUtil.getConnection();
            int update = qr.update(connection, sql, parameters);
            return update;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JDBCUtil.Close(null,null,connection);
        }
    }

    /**
     * 返回多行记录
     * @param sql
     * @param tClass
     * @param parameters
     * @param <T>
     * @return
     */
    public <T> List<T> queryMulti(String sql, Class<T> tClass, Object... parameters){
        Connection connection=null;
        try {
            connection= JDBCUtil.getConnection();
            return qr.query(connection, sql, new BeanListHandler<T>(tClass), parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JDBCUtil.Close(null,null,connection);
        }

    }

    /**
     * 返回单行
     * @param sql
     * @param tClass
     * @param parameters
     * @param <T>
     * @return
     */
    public <T> T querySingle(String sql, Class<T> tClass, Object... parameters){
        Connection connection=null;
        try {
            connection= JDBCUtil.getConnection();
            return qr.query(connection, sql, new BeanHandler<T>(tClass), parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JDBCUtil.Close(null,null,connection);
        }
    }

    /**
     * 返回单行单列
     * @param sql
     * @param parameters
     * @return
     */
    public Object queryScalar(String sql,Object...parameters){
        Connection connection=null;
        try {
            connection= JDBCUtil.getConnection();
            return qr.query(connection, sql, new ScalarHandler<>(),parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JDBCUtil.Close(null,null,connection);
        }
    }
}

当我们做好上述的准备工作后,再要去写代码查询user表里面的数据:
我们需要先写好一个javaBean用于数据传输
User.java

public class User {
    private String Sno;
    private String username;
    private String password;

    public String getSno() {
        return Sno;
    }

    public void setSno(String sno) {
        Sno = sno;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

java01.java

import java.util.List;


/**
 * @author hyl
 * @version 1.0
 * @date 2022/12/2-21:14
 */

public class Java01 {
    private static BasicDao dao=new BasicDao();
    public static void main(String [] args){
        List<User> users = dao.queryMulti("select * from user", User.class);
        for (User user : users) {
            System.out.println(user.getSno()+" "+user.getUsername()+" "+user.getPassword());
        }
    }
}

在这里插入图片描述
上面标红是因为一些时区的配置,不影响正常使用(强迫症就自己搜一下,加上对应的设置吧,这里不是重点)
通过上面和下面的对比,就可以明显的发现我们使用数据库连接池和工具包的好处。

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值