手动编写JDBC连接池应用适配器和装饰者模式

背景:

     为了对DBUtil更好的理解,所以决定自己手动编写一个连接池,众所周知,DBUtil是一个操作数据库的工具类,是对jdbc的简单封装,不会损耗数据库的性能,所以有的公司为了追求性能使用DBUtils,现在一个普遍的规律就是封装的越完善,性能就越低,首先说说Hibernate,因为这个纯粹的ORM框架,封装的特别的完善,所以性能便有所降低,如果应用到大型的项目中就会显得很笨重,MyBatis算是现在最流行的框架了,他是介于DBUtils和Hibernate之间的。那么下面就说说是如何手动编写的连接池吧,然后用上适配器和装饰者设计模式。

  1、首先来看看目录结构:

  

  2、然后编写自己的连接池: 

     首先创建一个池子,这个池子采用LinkedList,因为LinkedList插入删除比较方便,效率高,通过MyDataSource的构造方法初始化连接数,然后通过装饰者设计模式对conn对象进行加强(这里我们可以联想BufferedReader是如何创建对象的),然后编写获取池子和移除池子的方法

package com.itheima.datasourse;

import java.sql.Connection;
import java.util.LinkedList;


public class MyDataSource {
	//存储Connection资源的容器
		private static LinkedList<Connection> pool = new LinkedList<Connection>();
		
		public MyDataSource(int initCount){
			try {
				for(int i=0;i<initCount;i++){
					Connection conn = JDBCUtils.getConnection();
					
					//获得原始的conn对象 对该conn进行增强
					EnhanceConnection enhanceConn = new EnhanceConnection (conn);
					
					pool.add(enhanceConn);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		//提供一个获得池子中connection资源的方法
		public Connection getConnection(){
			return pool.removeFirst();
		}
		
		//提供一个将资源归还给池子的方法
		public static void giveBack(Connection conn){
			System.out.println("归还资源前池子中的资源数:"+pool.size());
			pool.addLast(conn);
			System.out.println("归还资源后池子中的资源数:"+pool.size());
		}
}

 3、编写AbstractDatasourse类:

    这个类去实现Connection接口,因为方法比较多,所以就不用代码展示了,里面没有自己敲的代码,括号里面是稍微比较官方的解释(当一个接口有多个抽象方法时,而我们只使用其中的一个或两个方法时,每次使用的时候我们都要重写这些方法,比较麻烦。我们可以定义一个类去实现这个接口,并重写里面的方法,只是方法体为空,并把这个类定义为抽象类,我们使用的时候继承这个类重写需要的方法就就可以了)

4、继承AbstractDatasourse类:

并且从写close方法和prepareStatement方法,因为有的时候我们写工具类的时候可能关闭后,池子里面的连接数就会变少,所以为了避免这种情况我们重写close方法:

package com.itheima.datasourse;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class EnhanceConnection extends AbstractDatasourse {
     private Connection conn;
	
	public EnhanceConnection(Connection conn){
		this.conn = conn;
	}
	
	//需要增强的方法 重写业务逻辑
	public void close() throws SQLException {
		//将conn返回池子中
		MyDataSource.giveBack(conn);
	}
	public PreparedStatement prepareStatement(String sql) throws SQLException {
		return conn.prepareStatement(sql);
	}
}

5、为了提高代码的复用性,我们将数据库的连接抽到配置文件中,把共有的功能抽取到JDBCUtil里面

package com.itheima.datasourse;

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtils {
	private static String driverClass = null;
	private static String url = null;
	private static String user = null;
	private static String password = null;
	
	static{
		try {
			//为四个变量参数赋值
			//获得配置文件 读取配置文件中的键值对 根据键获得对应值进行赋值
			InputStream in = new FileInputStream("D:\\workspace\\jiuyeday09\\LWEB10\\src\\jdbc.properties");
			//集合对象
			Properties pro = new Properties();
			pro.load(in);//将输入流中的键值对转换成Properties对象内部的键值对形式
			
			//通过Properties的getProperty(key)方法 获得对应的值value
			driverClass = pro.getProperty("driverClass");
			url = pro.getProperty("url");
			user = pro.getProperty("user");
			password = pro.getProperty("password");
			
			Class.forName(driverClass);//执行一次
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//获得链接对象的方法
	public static Connection getConnection() throws Exception{
		Connection conn = DriverManager
				.getConnection(url,user,password);
		return conn;
	}

	//关闭资源的方法
	public static void close(ResultSet rs,Statement stmt,Connection conn){

		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			} finally{
				rs = null;
			}
		}
		if(stmt!=null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			} finally{
				stmt = null;
			}
		}
		if(conn!=null){
			
		}	

	}
}
jdbc.properties配置文件中的内容:

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///student
user=root
password=root

6、编写测试类:

package com.itheima.datasourse;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;

public class MyDataSourceTest {
	@Test
	public void test() throws SQLException{
		//0、创建连接池对象
		MyDataSource dataSource = new MyDataSource(10);
		//1、从池子中获得一个资源对象
		Connection conn = dataSource.getConnection();
		//2、jdbc的操作
		PreparedStatement pstmt = conn.prepareStatement("select * from student");
		ResultSet rs = pstmt.executeQuery();
		while(rs.next()){
			System.out.println(rs.getString("name"));
			System.out.println(rs.getString("chinese"));
			System.out.println(rs.getString("english"));
			System.out.println(rs.getString("math"));
		}
		rs.close();
		pstmt.close();
		//3、将资源过还给池子
		conn.close();
		
	}
}

7、测试结果:


总结:

    敲完之后对许多东西有了新的认识,包括适配器,装饰者(包装类),而且更加了解了连接池的底层是如何实现的。相信明白了,在听到连接池,什么c3p0,DBUtil就不怕了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值