JDBC数据库连接池的实现

在网上搜数据库连接池的实现,跳出来一大堆,各式各样的。看到很多评论都说:现在都什么年代了还自己写连接池,现在成熟稳定的连接池有很多,我看到提到最多的是:C3P0;

确实C3P0用起来感觉不错,很方便,但是还是想自己尝试写写,不能局限于别人实现了,就直接拿来用,就不用思考了,这点很危险!可能自己写的东西没有技术牛人写的效率高,或许bug比较多,但是终究是自己的东西!

数据库连接池代码:

package com.hodmct.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;

import org.apache.log4j.Logger;

import com.hodmct.config.ConfigManager;
import com.hodmct.config.DataBaseConfig;

/**
 * 数据库连接池
 * 
 * @author quyongjin
 * @2013-4-10 下午02:22:47
 * @version V0.1
 */

public class DBConnectionPool {

    private Logger log = Logger.getLogger(DBConnectionPool.class);

    /** 使用的连接数 */
    private int inUsed = 0;

    /** 新建的连接数 */
    private int newConnNum = 0;

    /** 容器,空闲连接 */
    private ArrayList<Connection> freeConnections = new ArrayList<Connection>();

    /** 数据库配置类 */
    private DataBaseConfig dataConfig = ConfigManager.dataConfig;

    /**
     * 初始化线程池时创建最小数的连接
     */
    public DBConnectionPool() {
        synchronized (this) {
            for (int i = 0; freeConnections.size() < dataConfig
                    .getMinLinkConn(); i++) {
                Connection con = newConnection(); // 新建连接
                newConnNum++;
                freeConnections.add(con);
            }
        }
        log.info("最小连接数创建完毕,现有" + freeConnections.size() + "个连接!");
    }

    /**
     * 使用完之后释放连接
     */
    public synchronized void freeConnection(Connection con) {
        // 当con不为空时,调用该方法inUsed才减一
        if (con != null) {
            if (this.freeConnections.size() <= dataConfig.getMinLinkConn()) {
                // 添加到空闲连接的末尾
                this.freeConnections.add(con);
            } else {
                try {
                    con.close();
                    if(con.isClosed()){
                        this.newConnNum--;
                    }
                } catch (SQLException e) {
                    log.error("数据库连接关闭异常!",e);
                }
            }
            this.inUsed--;
        }
    }

    /**
     * 从连接池里得到连接
     * 
     * @return
     */
    public synchronized Connection getConnection() {
        Connection con = null;

        // 数据库连接数大于正在使用的连接数时才能创建新的连接
        if (dataConfig.getMaxLinkConn() > this.inUsed) {
            if (this.freeConnections.size() > 0) {
                con = (Connection) this.freeConnections.get(0);
                this.freeConnections.remove(0);// 如果连接分配出去了,就从空闲连接里删除
            } else {
                if (this.newConnNum < dataConfig.getMaxLinkConn()) {
                    con = newConnection(); // 新建连接
                    if(con != null){
                        this.newConnNum++;
                    }
                }
            }
            if (con != null) {
                this.inUsed++;
                log.info("从数据库连接池中得到连接,现剩余" + freeConnections.size() + "个空闲连接,"
                        + "现在有" + inUsed + "个连接在使用,创建了" + this.newConnNum +"个新连接!");
            }
        } else {
            log.info("数据库连接数已经达到最大连接数,不能获得连接!");
        }

        return con;
    }

    /**
     * 释放全部连接
     */
    @SuppressWarnings("rawtypes")
    public synchronized void release() {
        synchronized (this) {
            Iterator allConns = this.freeConnections.iterator();
            while (allConns.hasNext()) {
                Connection con = (Connection) allConns.next();
                try {
                    con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            this.freeConnections.clear();
            this.newConnNum = 0;
        }

    }

    private Connection newConnection() {
        Connection con = null;
        try {
            Class.forName(dataConfig.getDriver());
            con = DriverManager.getConnection(dataConfig.getUrl(),
                    dataConfig.getUser(), dataConfig.getPwd());
        } catch (ClassNotFoundException e) {
            log.error("缺少该数据库连接驱动,sorry!", e);
        } catch (SQLException e1) {
            log.error("不能创建连接,sorry!", e1);
        }
        return con;
    }

}
数据库配置类DataBaseConfig代码:
package com.hodmct.config;

/**
 * 链接数据库配置类
 * 
 * @author quyongjin
 * @2013-4-9 下午04:41:55
 * @version V0.1
 */

public class DataBaseConfig {
    
    /** 链接数据库驱动 */
    private String driver;
    
    /** 链接数据库的Url */
    private String url;
    
    /** 链接数据库的用户名 */
    private String user;
    
    /** 链接数据库的密码 */
    private String pwd;
    
    /** 最大连接数 */
    private int maxLinkConn;
    
    /** 最小连接数 */
    private int minLinkConn;

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUser() {
        return user;
    }

    public void setUser(String user) {
        this.user = user;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public int getMaxLinkConn() {
        return maxLinkConn;
    }

    public void setMaxLinkConn(int maxLinkConn) {
        this.maxLinkConn = maxLinkConn;
    }

    public int getMinLinkConn() {
        return minLinkConn;
    }

    public void setMinLinkConn(int minLinkConn) {
        this.minLinkConn = minLinkConn;
    }

}

读取数据库配置文件代码:

package com.hodmct.config;

import java.io.FileInputStream;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import com.hodmct.utils.XMLUtils;

/**
 * 读取databases.xml配置文件
 * 
 * @author quyongjin
 * @2013-4-9 下午05:15:24
 * @version V0.1
 */

public class ReadDataBasesConfigXML {
    
    private static Logger log = Logger.getLogger(ReadDataBasesConfigXML.class);
    
    /**
     * 无参的读取配置文件databases.xml方法
     */
    public static void databasesConfigLoad(){
        databasesConfigLoad(System.getProperty("user.dir") + "/config/databases.xml");
    }

    /**
     * 指定配置文件databases.xml路径的读取方法
     * @param xmlFilePath databases.xml 路径
     */
    private static void databasesConfigLoad(String xmlFilePath) {
        try {
            Document document = XMLUtils.parse(new FileInputStream(xmlFilePath));
            Element root = document.getRootElement();
            String driver = root.elementText("database-driver");
            if(driver != null && !"".equals(driver)){
                ConfigManager.dataConfig.setDriver(driver);
            }else{
                log.info("## 数据库驱动配置为空或读取有误!");
            }
            
            String url = root.elementText("database-url");
            if(url != null && !"".equals(url)){
                ConfigManager.dataConfig.setUrl(url);
            }else{
                log.info("## 数据库链接url为空或读取有误!");
            }
            
            String user = root.elementText("database-user");
            if(user != null && !"".equals(user)){
                ConfigManager.dataConfig.setUser(user);
            }else{
                log.info("## 数据库链接用户名为空或读取有误!");
            }
            
            String pwd = root.elementText("database-pwd");
            if(pwd != null && !"".equals(pwd)){
                ConfigManager.dataConfig.setPwd(pwd);
            }else{
                log.info("## 数据库链接密码为空或读取有误!");
            }
            
            String maxLinkConn = root.elementText("database-maxLinkConn");
            if(maxLinkConn != null && !"".equals(maxLinkConn)){
                int maxLinkConn_ = Integer.valueOf(maxLinkConn);
                ConfigManager.dataConfig.setMaxLinkConn(maxLinkConn_);
            }else{
                log.info("## 数据库最大连接数为空或读取有误!");
            }
            
            String minLinkConn = root.elementText("database-minLinkConn");
            if(minLinkConn != null && !"".equals(minLinkConn)){
                int minLinkConn_ = Integer.valueOf(minLinkConn);
                ConfigManager.dataConfig.setMinLinkConn(minLinkConn_);
            }else{
                log.info("## 数据库最小连接数为空或读取有误!");
            }
            
        } catch (Exception e) {
            log.error("## 服务器配置文件[serverconfig.xml]路径错误!",e);
        }
        
    }

}

数据库配置文件:

<?xml version="1.0" encoding="GBK"?>
<databases>
    <!-- 链接数据库驱动 -->
    <database-driver>com.microsoft.sqlserver.jdbc.SQLServerDriver</database-driver>
    <!-- 链接数据库的Url :SelectMethod=Cursor作用:利用服务器端的游标加快速度 使用:
    1.执行多个Statements的操作时候用
    2.需要手动使用事务的时候使用
    3.使用SqlServer数据库连接url的时候使用
    -->
    <database-url>jdbc:sqlserver://200.10.10.172:1433;DatabaseName=HOD-2000;selectMethod=cursor</database-url>
    <!-- 链接数据库的用户名 -->
    <database-user>sa</database-user>
    <!-- 链接数据库的密码  -->
    <database-pwd>brt123@brt</database-pwd>
    <!-- 最大连接数 -->
    <database-maxLinkConn>50</database-maxLinkConn>
    <!-- 最小连接数 -->
    <database-minLinkConn>20</database-minLinkConn>
</databases>
原文地址:https://www.cnblogs.com/quyongjin/p/3042591.html