文章目录
1.Druid的简单介绍
Druid(德鲁伊)是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。
官网:https://github.com/alibaba/druid(访问比较慢,所以你懂的)
要使用Druid连接池,首先把jar包导入项目,通过druid.properties配置文件进行配置。(配置文件名称自定义不是非得叫druid的)
- 普通的项目,没有使用maven进行管理的,需要自己去导入jar包;
- maven项目工程,直接在pom.xml中进行配置
Java 中的 properties 文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件。
- 文件的内容是格式是 “键=值”(key-value) 的格式。
- 在 properties 文件中,可以用"#" 来作注释。
properties文件在Java编程中用到的地方很多,操作很方便。
介于此,我们可以把数据库连接信息,如驱动、URL、账号、密码等这些动态信息不必写在class中,而放入一个可读取的配置的属性文件中,程序从属性文件中读取值以实现"运行时动态加载"。
常用的参数如下:
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 ="密码";//获取一个连接 connConnection conn =DriverManager.getConnection(url, user, password);
完整举例:
importjava.sql.*;/**
* @author hyl
* @version 1.0
* @date 2022/12/3-15:39
*/publicclass java02 {publicstaticvoidmain(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使用数据库连接池
**
好处:
**
- 资源重用 由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数量)。
- 更快的系统响应速度 数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。
- 新的资源分配手段 对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接池技术,几年钱也许还是个新鲜话题,对于目前的业务系统而言,如果设计中还没有考虑到连接池的应用。某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。
- 统一的连接管理,避免数据库连接泄漏 在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用连接。从而避免了常规数据库连接操作中可能出现的资源泄漏。
在说连接池的使用前,我们先说下Properties类与Properties配置文件
- Properties类与Properties配置文件 Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存属性集。不过Properties有特殊的地方,就是它的键和值都是字符串类型。
- 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
packagecom.hyl.sams.utils;importcom.alibaba.druid.pool.DruidDataSourceFactory;importjavax.sql.DataSource;importjava.io.FileReader;importjava.io.InputStream;importjava.sql.Connection;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;importjava.util.Properties;/**
* 德鲁伊连接池工具类
* 连接池工具类,连接数据库
* @author hyl
*/publicclassJDBCUtil{privatestaticDataSource source;//初始化连接static{Properties properties =newProperties();try{//使用ClassLoader加载配置文件,获取字节输入流InputStream is =JDBCUtil.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(is);
source =DruidDataSourceFactory.createDataSource(properties);}catch(Exception e){
e.printStackTrace();}}//获取连接publicstaticConnectiongetConnection()throwsSQLException{return source.getConnection();}/**
* 释放连接(不是断掉连接,而是归还释放)
* @param resultSet
* @param statement
* @param connection
*/publicstaticvoidClose(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){thrownewRuntimeException(e);}}}
上述代码,只需通过JDBCUtil.getConnection()就可以从池子里面获取一个连接,也只是方便我们去获取数据库的连接,但是当我们要去操作数据库的时候,还不是很方便,这里我们去借助第三方的数据库工具jar包,去简化我们的sql操作。
BasicDao.java
packagecom.hyl.sams.dao;importcom.hyl.sams.utils.Jdbc_Druid_Utils;importorg.apache.commons.dbutils.QueryRunner;importorg.apache.commons.dbutils.handlers.BeanHandler;importorg.apache.commons.dbutils.handlers.BeanListHandler;importorg.apache.commons.dbutils.handlers.ScalarHandler;importjava.sql.Connection;importjava.sql.SQLException;importjava.util.List;/**
* @author hyl
*/publicclassBasicDao{privateQueryRunner qr=newQueryRunner();//统一说明:Object... parameters// 是动态传参,参数个数0-n/**
* 插入、更新或删除
* @param sql
* @param parameters
* @return
*/publicintupdate(String sql,Object... parameters){Connection connection=null;try{
connection=JDBCUtil.getConnection();int update = qr.update(connection, sql, parameters);return update;}catch(SQLException e){thrownewRuntimeException(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,newBeanListHandler<T>(tClass), parameters);}catch(SQLException e){thrownewRuntimeException(e);}finally{JDBCUtil.Close(null,null,connection);}}/**
* 返回单行
* @param sql
* @param tClass
* @param parameters
* @param <T>
* @return
*/public<T>TquerySingle(String sql,Class<T> tClass,Object... parameters){Connection connection=null;try{
connection=JDBCUtil.getConnection();return qr.query(connection, sql,newBeanHandler<T>(tClass), parameters);}catch(SQLException e){thrownewRuntimeException(e);}finally{JDBCUtil.Close(null,null,connection);}}/**
* 返回单行单列
* @param sql
* @param parameters
* @return
*/publicObjectqueryScalar(String sql,Object...parameters){Connection connection=null;try{
connection=JDBCUtil.getConnection();return qr.query(connection, sql,newScalarHandler<>(),parameters);}catch(SQLException e){thrownewRuntimeException(e);}finally{JDBCUtil.Close(null,null,connection);}}}
当我们做好上述的准备工作后,再要去写代码查询user表里面的数据:
我们需要先写好一个javaBean用于数据传输
User.java
publicclassUser{privateStringSno;privateString username;privateString password;publicStringgetSno(){returnSno;}publicvoidsetSno(String sno){Sno= sno;}publicStringgetUsername(){return username;}publicvoidsetUsername(String username){this.username = username;}publicStringgetPassword(){return password;}publicvoidsetPassword(String password){this.password = password;}}
java01.java
importjava.util.List;/**
* @author hyl
* @version 1.0
* @date 2022/12/2-21:14
*/publicclassJava01{privatestaticBasicDao dao=newBasicDao();publicstaticvoidmain(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());}}}
上面标红是因为一些时区的配置,不影响正常使用(强迫症就自己搜一下,加上对应的设置吧,这里不是重点)
通过上面和下面的对比,就可以明显的发现我们使用数据库连接池和工具包的好处。
版权归原作者 想要登顶的菜鸟 所有, 如有侵权,请联系我们删除。