JDBC连接池封装(1)

一、为何要封装jdbc?

回顾:先复习一下JDBC的流程:JDBC六部曲

案例:通过jdbc查询表格,并且查看性能问题。

        //1.导包mysql驱动包---在官网里面下载即可//2.加载驱动Class.forName("com.mysql.cj.jdbc.Driver");//3.获取连接long t1 = System.currentTimeMillis();Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?serverTimezone=UTC","root","123456");long t2 = System.currentTimeMillis();//4.创建状态参数PreparedStatement pstate = conn.prepareStatement("SELECT * FROM TEST");//我查询的是test表格//5.执行操作//增删改查---executeUpdate//查询----executeQueryResultSet rs = pstate.executeQuery();//访问rs中的数据,进行遍历while (rs.next()){//对表格进行遍历输出System.out.print(rs.getString("name"));System.out.print(rs.getString("sex"));System.out.print(rs.getInt("age"));System.out.println(rs.getString("address"));}//6.关闭流rs.close();pstate.close();conn.close();//关闭连接long t3 = System.currentTimeMillis();System.out.println(t2-t1);//表示创建连接的时长System.out.println(t3-t2);//表示正常执行操作的时长

【运行结果】:可以看出创建连接的时长远远慢得多,性能不好。(有一部分是我的电脑性能不大好,时长比你们的更长一些)
在这里插入图片描述

二、存在的问题?

由以上代码可以看出的问题有:
1、jdbc的性能不好。(从运行结果可以看到,创建连接的时长太长)----解决的办法JDBC连接池的封装。
2、jdbc代码的冗余。(每次对数据库进行增删改查,都需要写一遍JDBC的流程,会很多余)----解决的办法ORM的封装。(后面单独有orm的笔记)

三、如何思考?如何解决?

分析问题:可以查看案例中的代码,每次创建连接之后,用完都需要关闭连接。
可以这样理解:①连接是桥梁,创建连接就是建桥,假如每次建桥需要3年,花10分钟过桥之后,把桥炸了。是不是很可惜?(炸了不行)
②那假如我不想关闭连接,就不想用完把桥炸了,那就每次建桥不炸,桥就会越来越多!这也行不通。(不炸也不行)
③那只能去限制建足够多的桥梁,让用户使用。这些桥梁(连接)需要放在一个地方(连接池)管理。连接是用来传输数据的,因而只能是单向的独木桥。用户如何得知哪座桥是可以使用的??因为connection类是别人写的,我们无法修改他人的代码,只能自己写一个类,里面可以写一个属性去监视桥是否被占用的状态。

具体代码实现:

  • 以下类是MyConnection,在获取连接的同时给连接设置状态,以便得知哪个连接是否被占用。
package pool;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;/*
这个类是我们自己创建的类
用来创建连接的 主要是将真实的连接和连接的状态绑定在一起
*/
public class MyConnection {//以下信息暂且固定private static String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";private static String user = "root";private static String password = "123456";private static String userName = "com.mysql.cj.jdbc.Driver";//写两个属性//两个属性会改变,不能设为静态的private boolean uesd = false;//false表示未占用,true表示已经被占用了private  Connection conn;//加载类,类只需要加载一次static {try {Class.forName(userName);} catch (ClassNotFoundException e) {e.printStackTrace();}}//有异常无法直接复制给属性,所以写在块里面{try {conn = DriverManager.getConnection(url,user,password);} catch (SQLException throwables) {throwables.printStackTrace();}}//get和set方法public  void setUesd(boolean uesd) {MyConnection.uesd = uesd;}public boolean isUsed() {return uesd;}//连接不需要设置,所以只有getpublic  Connection getConn() {return conn;}
}
  • 以下类是ConnectionPool,连接池的意思,用来管理许多的连接。
package pool;
import java.util.ArrayList;
import java.util.List;
public class ConnectionPool {//连接池---就是里面有很多连接,在这里面提供给用户连接的//属性是一个池子,里面装很多连接//方法:是获取连接的方法//里面放的是connection 还是 myconnection?  因为myconnection是具有状态的private List<MyConnection> pool = new ArrayList();//给连接池赋值,添加新的连接(暂时存放5个连接){for (int i=0 ; i<=5 ; i++){pool.add(new MyConnection());}}//创建获取连接的方法//返回值?返回myconnection,因为用户用完需要改状态的//参数?不需要参数public MyConnection getMC(){MyConnection result = null;//将返回值先设为空for (MyConnection c : pool){//在池子里面循环找if(!c.isUsed()){//表示未占用c.setUesd(true);//占用数据result = c;//将连接返回break;}}return result;}
}

【运行结果】:第一次创建5座桥(连接),耗时较长;根据结果得知,除了第一次加载,之后都比较快(和下载游戏加载类似)。

public static void main(String[] args) throws ClassNotFoundException, SQLException {//第一次连接//1.导包//2.加载驱动long t1 = System.currentTimeMillis();ConnectionPool connectionPool = new ConnectionPool();//3.获取连接MyConnection myConnection = connectionPool.getMC();Connection connection = myConnection.getConn();long t2 = System.currentTimeMillis();//4.创建状态参数  ---正常PreparedStatement pstate = connection.prepareStatement("SELECT * FROM TEST");//5.执行操作ResultSet rs = pstate.executeQuery();while (rs.next()){System.out.println(rs.getString("name"));}//6.关闭流rs.close();pstate.close();myConnection.setUesd(false);long t3 = System.currentTimeMillis();System.out.println(t2-t1);System.out.println(t3-t2);System.out.println("--------------------");//第二次连接//1.导包//2.加载驱动long t4 = System.currentTimeMillis();//3.获取连接MyConnection myConnection1 = connectionPool.getMC();Connection connection1 = myConnection1.getConn();long t5 = System.currentTimeMillis();//4.创建状态参数  ---正常PreparedStatement pstate1 = connection1.prepareStatement("SELECT * FROM TEST");//5.执行操作ResultSet rs1 = pstate1.executeQuery();while (rs1.next()){System.out.println(rs1.getString("name"));}//6.关闭流rs.close();pstate.close();myConnection.setUesd(false);long t6 = System.currentTimeMillis();System.out.println(t5-t4);System.out.println(t6-t5);

在这里插入图片描述

小结:

解决的问题:节省了时间,提高了性能。
发现的问题:由以上代码可以发现许多可以改进的问题
1.很多信息被写死了。(比如url,user,password,userName以及添加的连接5个)----解决办法:可以写在配置文件里面properties
2.连接池对象一个就够了。-----解决办法:单例设计模式
3.多个人同时访问怎样保证线程安全?----解决办法:synchronized关键字
4.若访问不到直接给null用户体验不好,如何处理?-----解决办法:等待机制
5.用户使用习惯发生很大变革。(main方法,现在的代码和之前的不一样,需要学习新的使用方式麻烦)-----解决方法:代理模式

留言:以上问题可以继续查看之后的笔记进行解决 ~


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部