日期:2014-05-16  浏览次数:20561 次

写了一个简单的数据库连接池,请帮忙看一下
我是一个新手,第一次发帖,以前都是看别人的帖子。
我写了一个简单的数据库连接池实现,感觉有很多欠缺的地方,希望各位指点一下。十分感谢。
有四个类:
(1)连接池配置对象 Config
(2)连接池主类 ConnectionPool
(3)Properties读取类  PropertyReader
(4)异常类 DBPoolException


ConnectionPool.java
  public class ConnectionPool {
	
	private static Logger logger = Logger.getLogger(ConnectionPool.class);
	//当前已用连接数
	private static volatile int curConnections = 0;
	
	private static Config config = null;
	
	//初始化成功标志
	private static boolean initFlag = false;
	
	private static volatile Stack<Connection> conns;
	static {
		PropertyReader pr = null;

		try {
			pr = new PropertyReader("pool-config.properties");
			config = new Config();
			//设置数据库驱动
			config.setDriver(pr.getValue("driver"));
			//url
			config.setUrl(pr.getValue("url"));
			//uername
			config.setUsername(pr.getValue("username"));
			//password
			config.setPassword(pr.getValue("password"));
			//最大连接数
			if(pr.getValue("maxConnections") != null){
				config.setMaxConnections(Integer.valueOf(pr.getValue("maxConnections")));
			}
			//初始化时最小连接数
			if(pr.getValue("minConnections") != null){
				config.setMinConnections(Integer.valueOf(pr.getValue("minConnections")));
			}
			//返还连接时是否提交
			if(pr.getValue("autoCommitOnClose") != null){
				config.setAutoCommitOnClose(Boolean.valueOf(pr.getValue("autoCommitOnClose")));
			}
			//当连接池用完时客户端调用getConn()后等待获取新连接的时间 
			//Default: (100毫秒)
			if(pr.getValue("checkoutTimeout") != null){
				config.setCheckoutTimeout(Integer.valueOf(pr.getValue("checkoutTimeout")));
			}
			//当没有可用链接时,尝试获取链接的次数
			if(pr.getValue("checkTimes") != null){
				config.setCheckTimes(Integer.valueOf(pr.getValue("checkTimes")));
			}
			initPool();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

	}
	/**
	 * 隐藏构造函数
	 */
	private ConnectionPool(){
		
	}
	
	/**
	 * 初始化连接池 保存minConnections个链接
	 * @throws SQLException
	 * @throws ClassNotFoundException 
	 */
	private static synchronized void initPool() throws SQLException, ClassNotFoundException{
		conns = new Stack<Connection>();
		Class.forName(config.getDriver());
		for(int i = 0 ; i < config.getMinConnections() ; i++){
			Connection conn = newConnection();
			conns.push(conn);
		}
		initFlag = true;
	}
	/**
	 * 获取一个可用链接
	 * @return
	 * @throws SQLException 
	 * @throws InterruptedException 
	 * @throws DBPoolException 
	 * @throws Exception
	 */
	public static Connection getConn() throws SQLException, InterruptedException, DBPoolException  {
		Connection conn = null;
		if (initFlag) {
			synchronized (conns) {
				// 循环次数
				int times = 0;
				while (null == conn && times < config.getCheckTimes() + 1) {
					times++;
					// 如果未达到最大链接
					if (curConnections < config.getMaxConnections()) {
						// 栈中未空
						if (!conns.isEmpty()) {
							conn = conns.pop();
							// 如果返回的链接不可用
							if (null == conn || conn.isClosed()) {
								conn = newConnection();
							}
						// 栈中空了
						} else {
							conn = newConnection();
						}
					} else {
						conns.wait(config.getCheckoutTimeout());
					}

				}
				if(null == conn){
					logger.warn("获取链接超时!!!!!");
					throw new DBPoolException("获取链接超时!!!!!");
				}else{
					curConnections++;
					conns.notifyAll();
				}

			}
		} else {
			logger.error("连接池初始化失败!!!!");
			throw new DBPoolException("连接池初始化失败!!!!");
		}

		return conn;
	}
	
	/**
	 * 归还一个链接
	 * @param conn
	 * @throws SQLException
	 * @throws InterruptedException
	 */
	public static void returnConn(Connection conn) throws SQLException, InterruptedException {
		synchronized (conns) {
			if (null != conn && !conn.isClosed()) {
				// 如果设置归还前自动提交为真
				if (config.isAutoCommitOnClose()) {
					conn.commit();
				} else {
					conn.rollback();
				}
			}
			int times = 0;
			//尝试归还5次 如果归还失败则关闭连接
			while (times < 6) {
				t