新手-手写一个简陋的数据库连接池(动态代理模式改造close()方法)

(新手)手写一个简陋的数据库连接池

  1. 首先,一个测试类poolDemo,这个类就是简单的从数据库里查询一条数据。代码如下。
package www.study.pool;

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

public class poolDemo {
	/*public static final String url="jdbc:mysql:///day11";
	public static final String username="root";
	public static final String password="************";*/
	public static void main(String[] args) {
		Connection conn=null;
		PreparedStatement pst=null;
		ResultSet rs=null;
		String sql="select * from account where id=?";
		MyPool pool=new MyPool();
		try {
			conn=pool.getConnection();
			pst=conn.prepareStatement(sql);
			pst.setString(1, "1");//index从1开始
			rs=pst.executeQuery();
			while(rs.next()){
				System.out.println("查询成功!");
				System.out.println(rs.getInt(3)+"元");//index从1开始
			}
		}catch(Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			if(rs!=null){
				try {
					rs.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					rs=null;//交给垃圾回收器处理。
				}
			}
			if(pst!=null){
				try {
					pst.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					pst=null;//交给垃圾回收器处理。
				}
			}
			if(conn!=null){
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					conn=null;//交给垃圾回收器处理。
				}
			}
		}
	}
		
}

  1. 然后是一个简陋数据库连接池MyPool类,里面使用静态代码块初始化 了5个连接,因为使用的时候会对增加,删除连接比较频繁,所以使用LinkedList链表的数据结构来存储连接。判断5个初始的连接是否用完了,用完的话就在生成5个连接出来。
  2. 接着使用动态代理模式,改造Connection的close()方法。当我们在测试类Pooldemo中使用conn.close()方法时,就会自动调用改造过的close()方法。代码如下。
package www.study.pool;

import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;

import javax.sql.DataSource;

public class MyPool implements DataSource {
//首先从连接池里初始化一批连接。使用LinkedList来储存。初始化过程放在静态代码块里
	private static LinkedList<Connection> list=new LinkedList<Connection>();
	public static final String url="jdbc:mysql:///day11";
	public static final String username="root";
	public static final String password="***********";
	static{
		for(int i=0;i<5;i++){//初始化5个
		try {
			Class.forName("com.mysql.jdbc.Driver");
			Connection conn=DriverManager.getConnection(url,username,password);
			list.add(conn);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			//我觉得这个地方需要做些处理,finally里面也是
		}
	}
		
}
	@Override
	public Connection getConnection() throws SQLException {
		// TODO Auto-generated method stub
		/**
		 * 如果初始化的连接没有了,那么就在生成5个出来,相当于每一批有5个连接。
		 */
		if(list.size()==0){
			for(int i=0;i<5;i++){
				try {
					Class.forName("com.mysql.jdbc.Driver");
					Connection conn=DriverManager.getConnection(url,username,password);
					list.add(conn);
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					//我觉得这个地方需要做些处理,finally里面也是
				}
			}
		}
		final Connection con=list.remove();
		//动态代理模式改造close()方法。
		Connection proxy=(Connection)Proxy.newProxyInstance(Connection.class.getClassLoader(), new Class[]{Connection.class}, new InvocationHandler(){

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				if("close".equals(method.getName())){
					System.out.println("close()方法只这里被调换了。。");
					returnConn(con);
					return null;
				}else{
					return method.invoke(con, args);
				}
				
			}
			
			
		});
		return proxy;//拿一个连接给人家用。
	}
	
	public void returnConn(Connection conn) throws SQLException{
		if(!conn.isClosed()&&conn instanceof Connection&&conn!=null){
			list.add(conn);//我觉得是不是不能用&&,得用||吧。
		}
	}
	

}

  1. 运行结果的截图:
    运行结果
    最后想说,在下是个新手,写的不好,欢迎指正。这在学习使用的c3p0之前,学习着手写一个简陋的数据库连接池,大家有谁手写的连接池不错的,可以推荐给我学习学习。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java动态数据库连接的示例代码: ``` import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class ConnectionPool { private String url; private String username; private String password; private List<Connection> connections = new ArrayList<>(); private int maxConnections; public ConnectionPool(String url, String username, String password, int maxConnections) { this.url = url; this.username = username; this.password = password; this.maxConnections = maxConnections; } public synchronized Connection getConnection() throws SQLException { if (connections.isEmpty()) { if (maxConnections == 0 || connections.size() < maxConnections) { Connection conn = DriverManager.getConnection(url, username, password); connections.add(conn); return conn; } else { throw new SQLException("Connection pool is full"); } } else { Connection conn = connections.remove(0); if (conn.isClosed()) { return getConnection(); } else { return conn; } } } public synchronized void releaseConnection(Connection conn) { connections.add(conn); } public synchronized void closeAllConnections() throws SQLException { for (Connection conn : connections) { conn.close(); } connections.clear(); } } ``` 使用方法: ``` ConnectionPool connectionPool = new ConnectionPool("jdbc:mysql://localhost:3306/mydb", "user", "password", 10); Connection conn = connectionPool.getConnection(); // Use the connection for database operations connectionPool.releaseConnection(conn); connectionPool.closeAllConnections(); ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值