自定义数据库连接池实现代码

一、数据库连接池的简单搭建

备注:其他方法未实现,不在代码中展现
MyDataSource.java
package com.util;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.sql.DataSource;

/**
 * 这是一个数据库连接池
 * 
 * 1.一开始先往池子里面放10个连接,创建10个连接
 * 2.来的程序通过getConnection获取连接
 * 3.用完之后,使用addBack归还连接
 * 4.扩容
 *
 */

public class MyDataSource implements DataSource{
	
	List<Connection> list = new ArrayList<Connection>();
	
	public MyDataSource() {
		
		for(int i = 0; i < 10; i++) {
			Connection conn = JDBCUtil.getConn();
			list.add(conn);
		}
	}
	
	/**
	 * 该连接池对外公布的获取连接的方法
	 */
	@Override
	public Connection getConnection(String arg0, String arg1) throws SQLException {
		//来拿连接的时候,先判断池子里是否有
		if(list.size() == 0) {
			for(int i = 0; i < 5; i++) {
				Connection conn = JDBCUtil.getConn();
				list.add(conn);
			}
		}
		Connection conn = list.remove(0);
		return conn;
	}
	
	/**
	 * 用完之后,记得归还
	 */
	public void addBack(Connection conn) {
		list.add(conn);
	}

}

二、数据库连接池的简单使用

package com.util;

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

import org.junit.Test;

public class TestPool {
	@Test
	public void testPool() {
		Connection conn = null;
		PreparedStatement ps = null;
		MyDataSource dataSource = new MyDataSource();
		try {
			
			conn = dataSource.getConnection1();
			
			String sql = "insert into account values (null , 'xilali' , 10)";
			if(conn==null){
				System.out.println("conn is null");
				}
			ps = conn.prepareStatement(sql);
			ps.executeUpdate();
			
		} catch (SQLException e) {
			e.printStackTrace();
		}finally {
			try {
				ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			//归还连接
			dataSource.addBack(conn);
		}
	}
}

三、自定义数据库连接池的问题

DataSource是Sun公司针对数据库连接池定义的一套规范。如果使用 一【数据库的简单搭建】中的代码,可能存在以下问题:
1.需额外记住addBack方法;
2.MyDataSource dataSource = new MyDataSource();多次调用,会创建多个连接池;
3.无法面向接口编程。原因如下:

UserDao dao = new UserDaoImpl(); dao.insert();
这是我们经常使用的两行代码,
如果将程序中的代码如下:
DataSource datasource = new MyDataSource();
由于接口里面没有定义addBack()方法,dataSource.addBack(conn)将报错。

4.如何解决这些问题?【以addBack()为切入点】

四、解决自定义数据库连接池出现的问题

由于多了addBack()方法,所以如果使用这个连接池,需要额外记住这个方法,且不能面向接口编程。
解决方法:修改接口中的close()方法。
Connection对象的close()方法,是关闭连接。修改这个close()方法,再次调用,并不是真的关闭,而是归还连接对象。

问题来了:如何扩展一个方法???

原有的方法逻辑,不是我们想要的,若想修改自己的逻辑,有以下几种方法:
1.改源码。无法实现。
2.继承。需知道这个接口的具体实现是哪个类。
3.使用装饰者模式。(√)
4.动态代理。(略)
使用方法:装饰者模式解决问题!!!!!!
1.定义类ConnectionWrap扩充方法close();

【备注:其他方法未实现,不在代码中展现】

public class ConnectionWrap  implements Connection{
	
	Connection connection = null;
	List <Connection> list ;
	public ConnectionWrap(Connection connection , List <Connection> list) {
		super();
		this.connection = connection;
		this.list = list;
	}

	@Override
	public void close() throws SQLException {
		//connection.close();
		System.out.println("有人来归还连接对象了。 归还之前,池子里面是:"+list.size());
		list.add(connection);
		System.out.println("有人来归还连接对象了。 归还之后...,池子里面是:"+list.size());
	}
	
	
	@Override
	public PreparedStatement prepareStatement(String sql) throws SQLException {
		return connection.prepareStatement(sql);
	}
}
	
2.修改MyDataSource.java中getConnection()方法;
/**
	 * 该连接池对外公布的获取连接的方法
	 */
	@Override
	public Connection getConnection(String arg0, String arg1) throws SQLException {
		//来拿连接的时候,先判断池子里是否有
		if(list.size() == 0) {
			for(int i = 0; i < 5; i++) {
				Connection conn = JDBCUtil.getConn();
				list.add(conn);
			}
		}
		Connection conn = list.remove(0);
		
		//在把这个对象抛出去的时候, 对这个对象进行包装。
		Connection connection = new ConnectionWrap(conn, list);
		
		return connection;
	}

这是关键!!!!!!!
//在把这个对象抛出去的时候, 对这个对象进行包装。
Connection connection = new ConnectionWrap(conn, list);

五、补充:装饰者模式

装饰者模式能够动态地将责任附加到对象上,在扩展对象功能方面比继承更加灵活,具体来说,装饰者模式将行为委托给相应的包装对象,并添加上自己的对应逻辑来实现特定的功能。
太官方了,我们还是用代码解释!
定义一个Waiter接口,接口里面有方法service(); ------>类似于Connection接口
public interface Waiter {
	void service();
}
定义一个类Waitress实现接口Waiter; ------>其中的service()类似于真正的close()方法
public class Waitress implements Waiter {

	@Override
	public void service() {
		System.out.println("在服务...");
	}
	
}
定义一个类WaitressWrap实现接口Waiter;------>其中的service()类似于扩充的(重写的)close()方法
public class WaitressWrap implements Waiter {
	
	Waiter watier  = null;
	public WaitressWrap(Waiter watier){
		this.watier = watier;
	}
	
	@Override
	public void service() {
		System.out.println("微笑...");
		watier.service();      //此service()执行的是类Waitress里的service()方法,(可要可不要)
	}
}
做个测试
public class MainTest {
	
	public static void main(String[] args) {
		/*
		Waiter waiter = new Waitress();
		waiter.service();
		*/
		WaitressWrap waitressWrap = new WaitressWrap(new Waitress());
		waitressWrap.service();	
	}
}
运行结果如下:
微笑…
在服务…

你可能感兴趣的:(自定义数据库连接池实现代码)