JDBC自定义连接池学习笔记

在大型项目中多次连接和释放数据库会造成资源浪费,使用连接池以节省资源。共享连接Connection,解决性能问题。实现javax.sql.DataSource连接池公共接口,常用的又DBCP,C3PO。

编写自定义连接池。MyDataSource类是自定义连接池类。

1、创建连接池,实现接口 2、提供集合 存放连接,因为需要经常添加和移除,选择LinkedList 3、需要连接时从集合中获取 4、使用完后归还

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedList;

import javax.sql.DataSource;

//自定义连接池代码实现
public class MyDataSource implements DataSource{//实现DataSource接口

	//1:创建容器储存Connection对象
	private static LinkedList<Connection> pool = new LinkedList<Connection>();
	//2:创建连接
	static{
		for(int i=0;i<5;i++)
		{
			Connection conn = JdbcUtils.getConn();
			pool.add(conn);
		}
	}

	//重写获取连接的方法 
	@Override
	public Connection getConnection() throws SQLException {
		//3:使用前先判断池中还有没有链接
		if(pool.size()==0)	
		{
			for(int i=0;i<5;i++)
			{
				Connection conn = JdbcUtils.getConn();
				pool.add(conn);
			}
		}
		//4:从池中获取连接对象
		return pool.remove(0);
	}
	
	//归还连接对象到连接池的方法
	public void back(Connection conn){
		pool.add(conn);
	}
	//更多实现方法没有给出
}

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

import org.junit.Test;

/*
 * JdbcUtils类,获取连接和释放资源的工具类  与之前相同没有改变
 * 
 * MyDataSource类,自定义连接池类 ,必须实现DataSource连接池公共接口,用工具类新建获取5个连接存入一个集合中
 * 
 * Test1 检测是否能正常使用的方法类  再获取连接时新建一个连接池对象并再连接池中获取连接 而不是直接从工具类中获取连接
 * 
 *观察最后finally中的方法,此时需要调用的是连接池对象的back方法释放资源。
 *    我们希望调用close的时候也进行归还,此时便需要对close方法进行增强。
 */


public class Test1 {

	@Test
	public void test123(){
		ResultSet rs = null;
		PreparedStatement pstmt = null;
		Connection conn =null;
		
		MyDataSource my = new MyDataSource();//创建连接池对象
		try {
			//从连接池获取连接
			conn=my.getConnection();
			
			//查询
			String sql = "select * from product where cid = ?";
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, "1");
			rs = pstmt.executeQuery();
			while(rs.next())
			{
				System.out.println("pid:"+rs.getObject(1)+" name:"+rs.getObject(2)+" cid:"+rs.getObject(5));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			my.back(conn);
		}
	}
}


此时编写的自定义连接池具有严重问题,想要使得调用调用close方法时不再是关闭而是归还,必须增强close方法,此时用的设计模式为装饰者设计模式。

1、编写类MyConnection 实现Connection接口,在其中修改close方法使得是归还而不是关闭,并且完善其他需要调用的方法。

2、在连接池类MyDataSource 中添加连接时添加上面编写的修改后的类。

3、在Test 的时候finally 中直接调用close方法 完整代码如下。

1 JdbcUtils类 与之前没有改变

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ResourceBundle;

public class JdbcUtils {

	private static String dirver;
	private static String url;
	private static String user;
	private static String password;
	
	static{
		ResourceBundle bundle = ResourceBundle.getBundle("db");//不用后缀名
		dirver = bundle.getString("jdbc.driver");		//获取配置文件中的字符串
		url = bundle.getString("jdbc.url");
		user = bundle.getString("jdbc.user");
		password = bundle.getString("jdbc.password");
	}
	public static Connection getConn()
	{
		Connection conn =null;
		try {
			Class.forName(dirver);
			conn = DriverManager.getConnection(url, user, password);	
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}
	public static void release(ResultSet rs,PreparedStatement pstmt,Connection conn)
	{
			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
	}
}

2、MyConnection类 实现连接接口  代码省略了部分没有用上的方法


//装饰者设计模式
 //1:实现要增强的类 Connection
public class MyConnection implements Connection{
	
	//定义变量
	private Connection conn;
	private LinkedList<Connection> pool;
	
	//2:编写构造方法,存入
	public MyConnection(Connection conn,LinkedList<Connection> pool){
		this.conn=conn;
		this.pool=pool;
	}
	
	//3:编写需要增强的方法
	@Override
	public void close() throws SQLException {
		//现在 如果调用此方法 需要将conn归还连接池中。
		//所以本类还需要连接池对象,让构造方法读入
		pool.add(conn);
	}
	@Override
	public PreparedStatement prepareStatement(String arg0) throws SQLException {
		return conn.prepareStatement(arg0);	//调用方法
	}
	@Override
	public Statement createStatement() throws SQLException {
		return conn.createStatement();
	}
	
	
	//省略更多没有用上的方法

}
3、MyDataSource 连接池类 省略了部分没有用上的方法

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedList;

import javax.sql.DataSource;

//自定义连接池代码实现
public class MyDataSource implements DataSource{

	private static LinkedList<Connection> pool = new LinkedList<Connection>();
	static{
		for(int i=0;i<5;i++)
		{
			//添加的时候,添加的是增强的类 已经经过改造
			Connection conn = JdbcUtils.getConn();
			MyConnection myconn = new MyConnection(conn,pool);
			pool.add(myconn);
		}
	}
 
	@Override
	public Connection getConnection() throws SQLException {
		if(pool.size()==0)	
		{
			for(int i=0;i<5;i++)
			{
				//添加增强类
				Connection conn = JdbcUtils.getConn();
				MyConnection myconn = new MyConnection(conn,pool);
				pool.add(myconn);
			}
		}
		//获取的也是已经增强过的对象
		return pool.remove(0);
	}
}
4、Test 检测

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

import org.junit.Test;

/*希望调用close时候也进行归还而不是关闭连接。使用装饰者设计模式,增强close方法
 * 
 * JdbcUtils类 工具类
 * 
 * MyDataSource类  往连接池里面添加连接的时候添加的是增强过的类对象
 * 
 * MyConnection类 , 实现Connection接口,重写close方法以及创建sql执行者的方法
 * 		此时调用close方法将进行归还而不是关闭
 *
 * Test1 检测 尝试插入
 * 
 */


public class Test1 {

	@Test
	public void test123(){
		Statement st = null;
		PreparedStatement pstmt = null;
		Connection conn =null;
		
		MyDataSource my = new MyDataSource();
		try {
			conn=my.getConnection();
			st = conn.createStatement();	//调用了conn的方法 需要在实现类中重写方法
			//添加:
			int r = st.executeUpdate("insert into product values(null,'王123',200,null,3)");
			System.out.println(r);	
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			JdbcUtils.release(null, pstmt, conn);	//区别:直接调用conn的close方法即可
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}









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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值