Java的JDBC连接池底层封装
目录
一、JDBC回顾
1.1 六个基本步骤
package test;
?
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
?
public class TestMain {
public static void main(String[] args) throws Exception {
//JDBC全称----JAVA DataBase Connectivity
//1.导包
//2.加载驱动类
Class.forName("com.mysql.cj.jdbc.Driver");
//3.获取连接,只是一个桥梁,负责让驱动与数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest?useSSL=false","root","12345678");
//4.获取状态参数(流)
//PreparedStatement预处理流
PreparedStatement pstat = connection.prepareStatement("select * from users");
//5.执行操作
//增删改---executeUpdate()
//查询---executeQuery()
//ResultSet底层---Set<Map<String,Object>>
ResultSet rs = pstat.executeQuery();
//6.访问下一个rs中的数据,遍历
while(rs.next()) {
System.out.print(rs.getInt("id"));
System.out.print(rs.getString("uname"));
System.out.print(rs.getString("psw"));
System.out.print(rs.getString("email"));
System.out.print(rs.getDate("birthday"));
System.out.print(rs.getDouble("sal"));
System.out.println();
}
//7.关闭资源
rs.close();
pstat.close();
connection.close();
}
?
}
1.2 问题的引出
1、JDBC代码流程写在哪个层次中?----DAO数据读写持久化层
2、DAO层中通常的方法什么样子?----对于数据库的增删改查操作
3、DAO方法中该写什么样的代码?----纯粹的JDBC流程 + SQL执行语句
4、DAO层次中的每一个方法里都存在JDBC流程(6步),流程大体上是一样的。所以DAO层次中的代码冗余问题就很多。------封装,也就是(ORM框架)
5、我们所说的JDBC连接池封装,其实是对我们现在的流程进行优化;我们现在所写的六个基本步中是存在很多问题的;而我们最后学的将整个JDBC封装是一个ORM框架;
二、ORM框架
1、ORM框架(Object Relationship Mapping对象关系映射)
(1)对象---domain
(2)关系---对应(映射)
2、ORM框架封装以后的最终效果,我们不用写JDBC流程了,只写SQL + 那些问号值;我们DAO层次中的方法没有执行体,只有方法的壳 + 注解(写SQL)
3、在ORM框架中讲解。
三、JDBC连接池性能优化
3.1 JDBC连接池在创建连接时优化
1、我们发现每次运行TestMain中的JDBC六步时都会有几秒卡顿,要进行优化
package test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class TestMain {
public static void main(String[] args) throws Exception {
//JDBC全称----JAVA DataBase Connectivity
//1.导包
//2.加载驱动类
long t1 = System.currentTimeMillis();
Class.forName("com.mysql.cj.jdbc.Driver");
//3.获取连接,只是一个桥梁,负责让驱动与数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbctest?useSSL=false","root","12345678");
long t2 = System.currentTimeMillis();
//4.获取状态参数(流)
//PreparedStatement预处理流
PreparedStatement pstat = connection.prepareStatement("select * from users");
//5.执行操作
//增删改---executeUpdate()
//查询---executeQuery()
//ResultSet底层---Set<Map<String,Object>>
ResultSet rs = pstat.executeQuery();
//6.访问下一个rs中的数据,遍历
while(rs.next()) {
System.out.print(rs.getInt("id"));
System.out.print(rs.getString("uname"));
System.out.print(rs.getString("psw"));
System.out.print(rs.getString("email"));
System.out.print(rs.getDate("birthday"));
System.out.print(rs.getDouble("sal"));
System.out.println();
}
//7.关闭资源
rs.close();
pstat.close();
connection.close();
long t3 = System.currentTimeMillis();
System.out.println(t2-t1);//794
System.out.println(t3-t2);//127
}
}
2、我们认为t1 和 t2 之间的时间是创建连接的时间,t2 和 t3 之间的时间是整个执行的时间
3、发现毫秒差很大,原因:
(1)DAO层的代码冗余问题
(2)JDBC流程中有一个性能卡顿,是在创建连接这个地方(由于每次进行数据操作都要去创建连接,每操作一次数据库,就会创建一次连接)
(3)解析:这个Connection就好比是一个桥梁,假如有5个人要过桥,但是此时并没有桥,每一个人都会先创建一个桥,然后过去之后再把桥炸了,然后第二个人想过桥会在创建一个桥过去之后在把桥炸了;所以每个人都会有创建桥的这个过程,里面增加了很多冗余。
4、如何提高创建连接的性能?
(1)假设我们创建5个连接,5个连接不销毁,留着复用。5个连接存在哪里?---集合(也就是连接池),还需要对集合进行管理
(2)需要将每一个连接身上绑定一个状态,连接类不是我们自己写的(Connection不是我们自己写的类),所以我们要创建一个新对象来将连接绑定状态。
3.2 将连接(桥梁)和状态进行绑定
1、MyConnection
1、MyConnection:描述一个真实连接和一个状态的关系,将一个真实可用连接和一个状态封装(绑定)在一起形成一个新的对象
(1)我们首先要在MyConnection类中创建连接和状态,最好是属性,创建属性的目的是为了描述对象的特征和状态;
//创建连接
private Connection conn;
//创建状态(false表示连接空闲--可用,true表示连接已被其他人占用--不可用)默认false;
private boolean used = false;
(2)上面创建了两个属性,发现conn连接这个属性它是没有完成连接操作的。所以我们创建一个普通块,目的是为了给我们创建的conn赋予一定的能力,就是为了我们每次new MyConnection的时候,能得到这个连接,这里的连接指的是让Java代码与数据库连接(桥梁);
{
//我们为什么不直接private Connection conn = DriverManager.getConnection();因为 DriverManager.getConnection();是有异常的
//这两行代码不能给属性,因为属性是不能抛异常的,而且属性这一行无法完成
Class.forName("");
conn = DriverManager.getConnection();
}
(3)那么问题来了,属性不是一个,因为每次new 都会创建新的属性,然后完成一次类加载,然后在创建桥梁,可是我们的类加载只需创建一次就够了啊,所以还需要创建一个静态块,目的为了让类加载执行一次
static {
//由于每new一次就执行一次普通块,所以把类加载放在静态块中
Class.forName("");
}
(4)连接需要获取get,让外界在创建对象时可以获取MyConnection对象中的连接(桥梁)getConn,让用户能获取到这个桥梁;used状态需要来回切换,所以还有set/get方法
//让外界能获取到连接(桥梁)
public Connection getConn() {
return conn;
}
//used状态需要来回切换
public boolean isUsed() {//boolean的get方法,名字是is开头的---规约
return used;
}
public void setUsed(boolean used) {
this.used = used;
}
(6)完整版
package pool;
import java.sql.Connection;
import java.sql.DriverManager;
/**
* @Description: TODO 描述一个真实连接和一个状态的关系
* 将一个真实可用连接(桥梁)和一个状态封装在一起形成一个新的对象MyConnection
* @Author: 曹宇希
* @Date: 2023/11/30 12:20
* @Version: 1.0
* @Company: 版权所有
*/
public class MyConnection {
private static String className = "com.mysql.cj.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/jdbctest?serverTimezone=GMT%2B8";
private static String user = "root";
private static String password = "12345678";
//连接
private Connection conn;
//状态(false表示连接空闲--可用,true表示连接已被其他人占用--不可用)默认false
private boolean used = false;
//一个静态块,目的为了让类加载执行一次
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!