JavaWeb学习-数据库连接池-2-装饰模式实现close

前面一篇介绍了数据库连接池,也就是说以后,我们一个业务处理完了,不应该直接调用mysql实现的close方法,而是要把这个连接对象放回到连接池中取,供下一个请求使用。本篇就来看看如何解决这个close方法的问题。前面一篇代码中模拟了连接池pool的实现,就是因为每个人都可以写自己的连接池实现,造成了不规范,为了规范这种行为,sun公司提供了一个接口javax.sql.DataSource,这样大家都去实现这个接口,别人看到你实现了这个接口的代码就明白了这是一个连接池的实现。

1.MyDataSource.java

写一个类实现接口javax.sql.DataSource

package com.anthony.pool;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.logging.Logger;

import javax.sql.DataSource;

import com.anthony.utils.DBUtils;

public class MyDataSource implements DataSource {
	
	//创建一个存放连接的池子,大小为10
	private static LinkedList<Connection> pool = (LinkedList<Connection>) Collections.synchronizedCollection(new LinkedList());
	
	static {
		try {
			for (int i = 0; i < 10; i++) {
				Connection conn = DBUtils.getConnection();
				pool.add(conn);
			}
		} catch (Exception e) {
			throw new ExceptionInInitializerError("初始化数据库连接失败,请检查配置文件。");
		}
	}
	
	public Connection getConnection() throws SQLException {
		Connection conn = null;
		if(pool.size() > 0) {
			conn = pool.removeFirst();
			//对conn进行包装
			MyConnection myConn = new MyConnection(conn, pool); //得到一个包装后的MyConnection对象
			return myConn;
		}else {
			// 1 等待
			// 2.等待超时,新创建一个连接
			throw new RuntimeException("服务器忙");
		}
	}

	public Connection getConnection(String username, String password) throws SQLException {
		return null;
	}
	
	@Override
	public PrintWriter getLogWriter() throws SQLException {
		return null;
	}

	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
		
	}

	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
		
	}

	@Override
	public int getLoginTimeout() throws SQLException {
		return 0;
	}

	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		return null;
	}

	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		return null;
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		return false;
	}

	
}

我们重点实现getConnection()方法,其他方法默认就好。

 

2.MyConnection.java

MyConnection类包装mysql中实现的Connection。

package com.anthony.pool;

import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

/*1)编写一个类,实现与被包装类相同的接口(具备相同的行为)
2)定义一个被包装类类型的变量
3)定义构造方法,把被包装类的对象注入,给包装类变量赋值。
4)对于不需要改写的方法,调用原有的方法。
5)对于需要改写的方法,写自己的代码。*/

public class MyConnection implements Connection {
	
	private Connection oldConnection;// com.mysql.jdbc.Connection
	private LinkedList<Connection> pool;
	
	public MyConnection(Connection oldConnection, LinkedList<Connection> pool) {
		this.oldConnection = oldConnection; //得到com.mysql.jdbc.Connection
		this.pool = pool; //得到连接池对象
	}
	
	@Override
	public void close() throws SQLException {
		pool.addLast(oldConnection); //把用完connection添加回集合中
	}
	
	@Override
	public PreparedStatement prepareStatement(String sql) throws SQLException {
		return oldConnection.prepareStatement(sql);
	}
	
	@Override
	public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
			throws SQLException {
		return oldConnection.prepareStatement(sql,resultSetConcurrency);
	}
	
	//以下省略多个实现方法

}

重点看构造方法和close方法。构造方法就是对conn对象进行包装,close方法就是把用户结束的连接对象进行放回到集合里。

 

3.TestJDBC.java

写一个测试类。

package com.anthony.pool;

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

import javax.sql.DataSource;

import org.junit.Test;

public class TestJDBC {
	
	@Test
	public void test() {
		DataSource ds = new MyDataSource();
		Connection conn = null;
		PreparedStatement ps = null;
		
		try {
			conn = ds.getConnection(); //从池中取出一个连接
			ps = conn.prepareStatement("select * from users");
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值