X.d 笔记

小Web,大世界

0%

JDBC连接池自己实现

有数据库的地方就少不了连接池。当然现在你导入的框架,包什么的都包含了连接池的相关工具,但最近做的项目特小,半个包都不想用,就自己写一个算了。

开始动手几经反转后终于成功写出一个简单的连接池,功能没有 jar 包里面的 DBConnectionPool强大,但足已经满足我的需求了,而且只有100行代码,简单方便!

下面是我的最终代码,朋友们拿去使用时请改为自己的配置

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Hashtable;

public class JDBCconnectPool{

    //连接失效时长,避免建立过多的conn闲置,或是程序异常没有关闭,这里设置30分钟
    private final static long expriationTime = 30*60*1000;
    //sql驱动类,连接信息
    public final static String DRIVER="com.jdbcDriver.mysqlOracleSqlserver";
    private String dsn,username,password;

    //定义两个HASHTABLE,一个存放正在被使用的连接,一个存放闲置的连接,对象的KEY为连接本身,
    private Hashtable<Connection ,Long> locked,unlocked;

    //构造方法,初始化连接需要的帐号密码
    public JDBCconnectPool(String dsn,String user,String pass){
        try {
            Class.forName(JDBCconnectPool.DRIVER).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        this.dsn=dsn;
        this.username=user;
        this.password=pass;
    }

    //生成一个连接
    private Connection createConnection() {
        try {
            return DriverManager.getConnection(dsn,username,password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    //销毁一个连接
    private void expireConnection(Connection conn) {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    //验证一个连接是否有效
    private boolean validateConnection(Connection conn) {
        try {
            return conn.isClosed();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    //从连接池里面得到一个连接
    public synchronized Connection getConn(){
        long now=System.currentTimeMillis();
        Connection conn=null;
        //如果闲置区有未被使用的连接,则优先取用
        if(unlocked.size()>0){
            //遍历每个连接,如果过期了或失效了则销毁,如果没失效,则转移至使用区并返回
            Enumeration<Connection> em=unlocked.keys();
            while(em.hasMoreElements()){
                conn=em.nextElement();
                long time=unlocked.get(conn);
                if((now-time)>expriationTime){
                    unlocked.remove(conn);
                    expireConnection(conn);
                }else{
                    if(validateConnection(conn)){
                        unlocked.remove(conn);
                        locked.put(conn, now);
                        return conn;
                    }else{
                        unlocked.remove(conn);
                        expireConnection(conn);
                    }
                }
            }
        }
        //创造一个新的连接,并放入使用区,再返回
        conn=createConnection();
        locked.put(conn, now);
        return conn;
    }

    //释放一个连接:用完之后把连接从使用区转到闲置区,以便需要的时候再拿出来使用
    public synchronized void releaseConn(Connection conn){
        long now=System.currentTimeMillis();
        locked.remove(conn);
        unlocked.put(conn, now);
    }

    public static void main(String[] args){
        JDBCconnectPool pool=new JDBCconnectPool("localhost:3306", "username", "password");
        Connection conn=pool.getConn();
        /**
         * TODO :使用conn的代码,用完之后释放
         * */
        pool.releaseConn(conn);
    }

}