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>