实现一个简单的数据库连接池

说明

看到团长公众号的文章,自己参照完成一个简单的数据库连接池

正文

ConnPool 连接池类必须实现javax.sql.DataSource接口

package com.datasource.connpool;

import java.io.IOException;
import java.io.InputStream;
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.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.Properties;
import java.util.logging.Logger;

import javax.sql.DataSource;

/**
 * 简单实现数据库连接池
 * 采用代理模式
 * @author wds
 *
 */
public class ConnPool implements DataSource {

    //使用LinkedList集合存放数据库连接
    private static LinkedList<Connection> connPool = new LinkedList<Connection>();

    //在静态代码块中加载配置文件
    static{
        InputStream in = ConnPool.class.getClassLoader().getResourceAsStream("db.properties");
        Properties prop = new Properties();
        try {
            prop.load(in);
            String driver = prop.getProperty("driver");
            String url = prop.getProperty("url");
            String user = prop.getProperty("user");
            String password = prop.getProperty("password");
            //数据库连接池的初始化连接数的大小
            int  InitSize = Integer.parseInt(prop.getProperty("InitSize"));
            //加载驱动
            Class.forName(driver);
            for(int i = 0; i < InitSize; i++){
                Connection conn = DriverManager.getConnection(url, user, password);
                //将创建的连接添加的list中
                System.out.println("初始化数据库连接池,创建第 " + (i + 1) +" 个连接,添加到池中");
                connPool.add(conn);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取数据库连接
     */
    public Connection getConnection() throws SQLException {
        if(connPool.size() > 0){
            //从集合中获取一个连接
            final Connection conn = connPool.removeFirst();
            //返回Connection的代理对象
            return (Connection) Proxy.newProxyInstance(ConnPool.class.getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                    if(!"close".equals(method.getName())){
                        return method.invoke(conn, args);
                    }else{
                        connPool.add(conn);
                        System.out.println("关闭连接,实际还给了连接池");
                        System.out.println("池中连接数为 " + connPool.size());
                        return null;
                    }
                }
            });
        }else{
            throw new RuntimeException("数据库繁忙,稍后再试");
        }
    }

    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    public void setLoginTimeout(int seconds) throws SQLException {

    }

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

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

    public Object unwrap(Class iface) throws SQLException {
        return null;
    }

    public boolean isWrapperFor(Class iface) throws SQLException {
        return false;
    }

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


}

JdbcUtil 工具类 通过此类从连接池中获取连接

package com.datasource.util;

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

import com.datasource.connpool.ConnPool;

/**
 * 获取连接的工具类
 * @author wds
 *
 */
public class JdbcUtil {

    //数据库连接池
    private static ConnPool  connPool = new ConnPool();

    /**
     * 从池中获取一个连接
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException{
        return connPool.getConnection();
    }

    /**
     * 关闭连接
     * @param conn
     * @param st
     * @param rs
     * @throws SQLException 
     */
    public static void CloseConnection(Connection conn, Statement st, ResultSet rs) throws SQLException{

        // 关闭存储查询结果的ResultSet对象
        if(rs != null){
                rs.close();
        }

        //关闭Statement对象
        if(st != null){
                st.close();
        }

        //关闭连接
        if(conn != null){
                conn.close();
        }
    }

}

PoolTest 测试类

package com.datasource.test;

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

import com.datasource.util.JdbcUtil;

public class PoolTest {

    /**
     * 测试数据库连接池
     * @param args
     */
    @SuppressWarnings("all")
    public static void main(String[] args) {
        JdbcUtil util = new JdbcUtil();
        try {
            Connection conn = util.getConnection();
            if(conn != null){
                System.out.println("我得到了一个连接");
            }
            util.CloseConnection(conn, null, null);
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

}

测试结果

在测试时,发现一个问题,当数据库连接驱动版本过低时,会发生异常
这里写图片描述

这里写图片描述
通过查找解决方法,发现是由于驱动版本的问题,网上的解决方法是将conn.getClass().getInterfaces() 改为 new Class[] {Connection.class} ,这里我改变了驱动的版本,使用高版本可以成功

这里写图片描述

这里写图片描述

源码放在了GitHub上:https://github.com/Edenwds/javaweb/tree/master/ConnPool

  • 5
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值