JDBC高级续
自定义数据库连接池
1.DataSource 接口概述
javax.sql.DataSource 接口:数据源(数据库连接池)。Java 官方提供的数据库连接池规范(接口)
如果想完成数据库连接池技术,就必须实现 DataSource 接口
核心功能:获取数据库连接对象:Connection getConnection();
2.自定义数据库连接池
1 定义一个类,实现 DataSource 接口。
2 定义一个容器,用于保存多个 Connection 连接对象。
3 定义静态代码块,通过 JDBC 工具类获取 10 个连接保存到容器中。
4 重写 getConnection 方法,从容器中获取一个连接并返回。
5 定义 getSize 方法,用于获取容器的大小并返回。
-
例如1
//1.定义一个类,实现 DataSource 接口 public class MyDataSource implements DataSource { //2.准备一个容器。用于保存多个数据库连接对象 private static List<Connection> pool = Collections.synchronizedList(new ArrayList<>()); //2.定义静态代码块,获取多个连接对象保存到容器中 static{ for(int i = 1; i <= 10; i++) { //通过工具类获取连接对象 Connection con = JDBCUtils.getConnection(); pool.add(con); } } //4.提供一个获取连接池大小的方法 public int getSize() { return pool.size(); } ...略 }
案例2
//1.定义一个类实现 DataSource接口 public class Demo001 implements DataSource { //2.准备一个容器。用于保存多个数据库连接对象 private List<Connection> pool; //3/ public Demo001() { pool = new ArrayList<>(); for (int i = 0; i < 10; i++) { Connection conn = JDBCUtils.getConnection(); pool.add(conn); } } //4.提供一个获取连接池大小的方法 public int getSize() { return pool.size(); }
3.自定义数据库连接池的测试 测试功能是否完成
归还 数据库的连接
1.继承方式
继承方式归还数据库连接的思想
通过打印连接对象,发现 DriverManager 获取的连接实现类是 JDBC4Connection
那我们就可以自定义一个类,继承 JDBC4Connection 这个类,重写 close() 方法,完成连接对象的归还
继承方式的实现步骤
//1.定义一个类,继承JDBC4Connection
public class MyConnection1 extends JDBC4Connection{//1.定义一个类,继承JDBC4Connection
//2.定义Connection连接对象和容器对象的成员变量
private Connection con;
private List<Connection> pool;
//3.通过有参构造方法为成员变量赋值
public MyConnection1(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url,Connection con,List<Connection> pool) throws SQLException {
super(hostToConnectTo, portToConnectTo, info, databaseToConnectTo, url);
this.con = con;
this.pool = pool;
}
//4.重写close方法,完成归还连接
@Override
public void close() throws SQLException {
pool.add(con);
}
}
继承方式归还数据库连接存在的问题
通过查看 JDBC 工具类获取连接的方法发现:我们虽然自定义了一个子类,完成了归还连接的操作。
但是 DriverManager 获取的还是 JDBC4Connection 这个对象,并不是我们的子类对象,而我们又不能整体去修改驱动包中类的功能,所继承这种方式行不通!
2.装饰者模式
装饰设计模式归还数据库连接的思想
我们可以自定义一个类,实现 Connection 接口。这样就具备了和 JDBC4Connection 相同的行为了
重写 close() 方法,完成连接的归还。其余的功能还调用 mysql 驱动包实现类原有的方法即可
实现步骤
//1.定义一个类,实现Connection接口
public class MyConnection2 implements Connection{
//2.定义连接对象和连接池容器对象的成员变量
private Connection con;
private List<Connection> pool;
//3.通过有参构造方法为成员变量赋值
public MyConnection2(Connection con,List<Connection> pool) {
this.con = con;
this.pool = pool;
}
//4.重写close方法,完成归还连接
@Override
public void close() throws SQLException {
pool.add(con);
}
//5.剩余方法,还是调用原有的连接对象中的功能即可
@Override
public Statement createStatement() throws SQLException {
return con.createStatement();
}
...略
}
装饰设计模式归还数据库连接存在的问题
实现 Connection 接口后,有大量的方法需要在自定义类中进行重写
3.适配器设计模式
适配器设计模式归还数据库连接的思想
我们可以提供一个适配器类,实现 Connection 接口,将所有方法进行实现(除了close方法)
自定义连接类只需要继承这个适配器类,重写需要改进的 close() 方法即可
实现步骤1 定义一个适配器类
//1.定义一个适配器类。实现Connection接口
public abstract class MyAdapter implements Connection {
//2.定义连接对象的成员变量
private Connection con;
//3.通过有参构造为变量赋值
public MyAdapter(Connection con) {
this.con = con;
}
//4.重写所有的抽象方法(除了close)
@Override
public Statement createStatement() throws SQLException {
return con.createStatement();
}
...其余方法
实现步骤2 定义一个类继承适配器类
//1.定义一个类,继承适配器类
public class MyConnection3 extends MyAdapter {
//2.定义连接对象和连接池容器对象的成员变量
private Connection con;
private List<Connection> pool;
//3.通过有参构造为变量赋值
public MyConnection3(Connection con,List<Connection> pool) {
super(con);
this.con = con;
this.pool = pool;
}
//4.重写close方法,完成归还连接
@Override
public void close() {
pool.add(con);
}
}
适配器设计模式归还数据库连接存在的问题
自定义连接类虽然很简洁了,但适配器类还是我们自己编写的,也比较的麻烦
4.动态代理方式
动态代理:在不改变目标对象方法的情况下对方法进行增强
组成
被代理对象:真实的对象
代理对象:内存中的一个对象
要求
代理对象必须和被代理对象实现相同的接口
实现
Proxy.newProxyInstance()
案例
//先定义一个接口
public interface StudentInterface {
void eat(String name);
void study();
}
//再定义一个类实现接口
public class Student implements StudentInterface{
public void eat(String name) {
System.out.println("学生吃" + name);
}
public void study() {
System.out.println("在家自学");
}
}
/*要求:在不改动Student类中任何的代码的前提下,通过study方法输出一句话:来xx学习
类加载器:和被代理对象使用相同的类加载器
接口类型Class数组:和被代理对象使用相同接口
代理规则:完成代理增强的功能*/
public class Test {
public static void main(String[] args) {
Student stu = new Student();
StudentInterface proxyStu = (StudentInterface) Proxy.newProxyInstance(stu.getClass().getClassLoader(), new Class[]{StudentInterface.class}, new InvocationHandler() {
/*
执行Student类中所有的方法都会经过invoke方法
对method方法进行判断
如果是study,则对其增强
如果不是,还调用学生对象原有的功能即可
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("study")) {
System.out.println("来黑马学习");
return null;
}else {
return method.invoke(stu,args);
}
}
});
proxyStu.eat("米饭");
proxyStu.study();
}
}
动态代理模式
作用: 在不改变原有类的情况下,增强原有类的功能