java基础——数据库连接池(1)从技术演进角度阐述

java基础


三篇文章:
第一篇——从技术角度阐述为什么使用数据库连接池
第二篇——将传统连接和数据库连接池对比
第三篇——总结连接池的好处,工作原理,存在的问题,常用连接池


这篇博客从技术演进发展的角讲解 为什么使用数据库连接池

一、早期通过JDBC方式操作数据库

我们先来看早期使用JDBC的方式操作数据库的过程,这里以mysql数据库为例讲解

在这里插入图片描述

JDBC操作数据库原理:一般来说,java应用程序访问数据库的过程是:

①装载数据库驱动程序;

②通过jdbc建立数据库连接;

③访问数据库,执行sql语句;

④断开数据库连接。

1、具体的代码实现步骤

创建数据库配置文件db.properties ,配置文件内容如下:

#连接数据库的url,test表示数据库名,useUnicode=true表示使用Unicode字符集
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8; 
#用户名
user=root
#密码
password=root
#MySQL数据库加载驱动
driverClass=com.mysql.jdbc.Driver

定义一个使用jdbc连接数据库的工具类JdbcUtil.java

public class JdbcUtil{
    //定义全局变量
    private static String url = null;
    private static String user = null;
    private static String password = null;
    private static driverClass = null;
    //读取配置文件内容,放在静态代码块中就行,因为只需要加载一次就可以了
    static{
        try{
            Properties props = new Properties();
            //使用类路径加载的方式读取配置文件
            //读取的文件路径要以“/”开头,使用"/"开头会直接定位到工程的src路径下
            InputStream in = JdbcUtil.class.getResourceAsStream("/db.properties");
            //加载配置文件
            props.load(in);
            //读取配置文件信息
            url = props.getProperty("url");
            user = props.getProperty("user");
            password = props.getProperty("password");
            driverClass = props.getProperty("driverClass");
            //动态注册mysql驱动程序
            Class.forName(driverClass);
            System.out.println("成功加载MySQL驱动程序");
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("mysql驱动程序注册失败!!!");
        }
    }
 
    //获取连接对象Connection
    public static Connection getConnection(){
        try{
            //要连接数据库,需要向java.sql.DriverManager请求并获得Connection对象
            return DriverManager.getConnection(url,user,password);
        }catch(SQLException e){
            e.printStackTrace();
            //抛出运行时异常
            throw new RuntimeException();
        }
    }
 
    //关闭连接的方法,后打开的先关闭
    public static void close(Connection conn,Statement stmt,ResultSet rs){
        //关闭ResultSet对象
        if(rs != null){
            try{
                //关闭rs,设置rs=null,因为java会优先回收值为null的变量
                rs.close();
                rs = null;
            }catch(SQLException e){
                e.printStackTrace();
                throw new RuntimeException();
            }
        }
        //关闭Statement对象,因为PrepareStatement和CallableStatement都是Statement的子接口,所以这里只需要有关闭Statement对象的方法就可以了
        if(stmt != null){
            try{
                stmt.close();
                stmt = null;
            }catch(SQLException e){
                e.printStackTrace();
                throw new RuntimeException();
            }
        }
        //关闭Connection对象
        if(conn != null){
            try{
                conn.close();
                conn = null;
            }catch(SQLException e){
                e.printStackTrace();
                throw new RuntimeException();
            }
        }
    }
}

到此,这是一个完整的使用JDBC方式操作数据库的过程,下面我们新建一个测试类TestConn.java 测试一下

package demo;
 
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import utils.JdbcUtil;
 
public class TestConn {
 
	public static void main(String[] args) {
	// TODO Auto-generated method stub
	Connection conn = JdbcUtil.getConnection();
	  try {
		Statement stmt = conn.createStatement();
		ResultSet rs = stmt.executeQuery("SELECT * FROM user") ;
		//使用结果集(ResultSet)对象的访问方法获取数据:
		 while(rs.next()){   
	         String name = rs.getString("name") ; 
	         System.out.println(name);
	         String pass = rs.getString(1);//此方法比较高效,列是从左到右编号的,并且从列1开始 
	         System.out.println(pass);
	     } 
		 //操作完成以后关闭JDBC对象,要把所有使用的JDBC对象全都关闭,以释放JDBC资源,关闭顺序和声明顺序相反: 
		 //关闭顺序1、关闭记录集,2、关闭声明,3、关闭连接对象
		 JdbcUtil.close(conn, stmt, rs);
	  } catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	  }
	}
}

2、分析
 程序开发过程中,存在很多问题:首先,每一次web请求都要建立一次数据库连接。建立连接是一个费时的活动,每次都得花费0.05s~1s的时间,而且系统还要分配内存资源。这个时间对于一次或几次数据库操作,或许感觉不出系统有多大的开销。可是对于现在的web应用,尤其是大型电子商务网站,同时有几百人甚至几千人在线是很正常的事。在这种情况下,频繁的进行数据库连接操作势必占用很多的系统资源,网站的响应速度必定下降,严重的甚至会造成服务器的崩溃。不是危言耸听,这就是制约某些电子商务网站发展的技术瓶颈问题。其次,对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将不得不重启数据库。还有,这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。

 上述的用户查询案例,如果同时有1000人访问,就会不断的有数据库连接、断开操作:
在这里插入图片描述
 通过上面的分析,我们可以看出来,“数据库连接”是一种稀缺的资源,为了保障网站的正常使用,应该对其进行妥善管理。其实我们查询完数据库后,如果不关闭连接,而是暂时存放起来,当别人使用时,把这个连接给他们使用。就避免了一次建立数据库连接和断开的操作时间消耗。原理如下:
在这里插入图片描述

二、技术演进出来的数据库连接池

 由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理。我们知道,对于共享资源,有一个很著名的设计模式:资源池(resource pool)。该模式正是为了解决资源的频繁分配﹑释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量﹑使用情况,为系统开发﹑测试及性能调整提供依据。

 我们自己尝试开发一个连接池,来为上面的查询业务提供数据库连接服务:

  ① 编写class 实现DataSource 接口

  ② 在class构造器一次性创建10个连接,将连接保存LinkedList中

  ③ 实现getConnection 从 LinkedList中返回一个连接

  ④ 提供将连接放回连接池中方法

1、实现mysql数据库连接池代码

public class MyDataSource implements DataSource {
    //链表实现栈结构
    privateLinkedList<Connection> dataSources = new LinkedList<Connection>();
    //无参构造器,初始化连接数量
    public MyDataSource() {
         //一次性创建10个连接
         for(int i = 0; i < 10; i++) {
            try {
              //1、获取数据库连接对象
              Connection conn = JdbcUtil.getConnection();
              //2、将连接加入连接池中
              dataSources.add(con);
            } catch (Exception e) {
              e.printStackTrace();
          }
       }
     }
 
     @Override
     public Connection getConnection() throws SQLException {
         //取出连接池中一个连接
         final Connection conn = dataSources.removeFirst(); //删除第一个连接返回
         return conn;
     }
 
     //将连接放回连接池
     public void releaseConnection(Connection conn) {
         dataSources.add(conn);
     }
}

小结:
 这篇博客从技术发展的角度讲解,为什么要用数据库连接池,根本原因就是减轻资源的频繁分配,也叙述了数据库连接池的工作原理。

本来自己要写的
但是写的太好直接转载了【https://blog.csdn.net/shuaihj/article/details/14223015】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值