Java 数据库连接池

adolphus 贡献于2011-11-15

作者 null  创建于2011-10-12 03:44:00   修改者cnnic  修改于2011-10-12 03:44:00字数6604

文档摘要:基本概念及原理、 数据库连接池是为了解决数据库对象的共享出错问题。 实际就是建立一个缓冲池。 预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从连接池中取出一个,使用完毕之后再放回去。
关键词:

JAVA数据库连接池 l 基本概念及原理 n 数据库连接池是为了解决数据库对象的共享出错问题。 n 实际就是建立一个缓冲池。 n 原理 预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从连接池中取出一个,使用完毕之后再放回去。 n JDBC的API中没有提供连接池的方法。 l 连接池关键问题分析 n 使用线程同步来解决并发问题 n 使用一个单例模式的连接池管理类来解决连接多个不同数据库。具体方法: u 在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url地址()、用户名()、密码()等信息。如tx.url=172.21.15.123:5000/tx_it,tx.user=yang,tx.password=yang321。 u 根据资源文件提供的信息,创建多个连接池类的实例,每一个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字,通过不同的名字来管理不同的连接池。 n 使用资源文件来解决同一个数据库有多个用户使用不同的名称和密码访问的情况。具体方法: u 资源文件中设置多个具有相同url地址,但具有不同用户名和密码的数据库连接信息。 n 可采用每一个事务独占一个连接来实现事务处理, 这种方法可以大大降低事务管理的复杂性。具体方法: u Connection类可以通过设置Connection的AutoCommit属性为false,然后显式的调用commit或rollback方法来实现。 n 使用空闲池来解决连接池的分配与释放处理。具体办法: u 把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。 u 每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接: l 如果有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的判断,如果可用就分配给用户,如不可用就把这个连接从空闲池删掉,重新检测空闲池是否还有连接)。 l 如果没有则检查当前所建连接池是否达到连接池所允许的最大连接数(maxConn),如果没有达到,就新建一个连接,如果已经达到,就等待一定的时间(timeout)。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户,如果等待时间超过预定时间timeout,则返回空值(null)。 u 系统对已经分配出去正在使用的连接只做计数,当使用完后再返还给空闲池。 n 连接池的配置与维护 u 连接池中到底应该放置多少连接,才能使系统的性能最佳? l 设置连接最小数(系统启动时连接池所创建的连接数)、最大数(使用连接池时所允许连接最大连接数目) u 如何确保连接池中的最小连接数呢? l 动态策略: 每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。 l 静态策略: 发现空闲连接不够时再去检查。 l 连接池的实现 n 连接池模型 u DBConnectionPoolManager( 连接池管理外覆类(wrapper),符合单例模式) l u DBConnectionPool(连接池内部类) l 从连接池获取或创建可用连接; public Connection getConnection() l 使用完毕之后,把连接返还给连接池; public synchronized void freeConnection(Connection con) l 在系统关闭前,断开所有连接并释放连接占用的系统资源; public synchronized void release() l 还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。 private int checkedOut;//已被分配出去的连接数 private int minConn;//连接池里连接的最小数量 private int maxConn;//连接池里允许存在的最大连接数 private String name; //为这个连接池取个名字,方便管理 应用示例: import java.io.*; import java.sql.*; import java.util.*; import java.util.Date; //建立DBConnectionManager public class DBConnectionManager { static private DBConnectionManager instance; static private int clients; private Vector drivers = new Vector(); private PrintWriter log; private Hashtable pools = new Hashtable(); // 返回唯一的实列 static synchronized public DBConnectionManager getInstance() { if (instance == null) { instance = new DBConnectionManager(); } clients++; return instance; } // 构造函数! private DBConnectionManager() { init(); } // 结束构造函数 // 释放一个连接 public void freeConnection(String name, Connection con) { DBConnectionPool pool = (DBConnectionPool) pools.get(name); if (pool != null) { pool.freeConnection(con); } } // 结束释放一个连接 // 取得一个连接 public Connection getConnection(String name) { DBConnectionPool pool = (DBConnectionPool) pools.get(name); if (pool != null) { return pool.getConnection(); } return null; } public Connection getConnection(String name, long time) { DBConnectionPool pool = (DBConnectionPool) pools.get(name); if (pool != null) { return pool.getConnection(time); } return null; } // 结束getconnection // 关闭所有连接 public synchronized void release() { { if (--clients != 0) return; } Enumeration allPools = pools.elements(); while (allPools.hasMoreElements()) { DBConnectionPool pool = (DBConnectionPool) allPools.nextElement(); pool.release(); } Enumeration allDrivers = drivers.elements(); while (allDrivers.hasMoreElements()) { Driver driver = (Driver) allDrivers.nextElement(); try { DriverManager.deregisterDriver(driver); log("撤消JDBC驱动程序" + driver.getClass().getName()); } catch (SQLException e) { log(e, "无法撤消JDBC驱动程序的注册" + driver.getClass().getName()); } } } private void createPools(Properties props) { Enumeration propNames = props.propertyNames(); while (propNames.hasMoreElements()) { String name = (String) propNames.nextElement(); if (name.endsWith(".url")) { String poolName = name.substring(0, name.lastIndexOf(".")); String url = props.getProperty(poolName + ".url"); if (url == null) { log("没有连接池" + poolName + "指定的URL"); continue; } String user = props.getProperty(poolName + ".user"); String password = props.getProperty(poolName + ".password"); String maxconn = props.getProperty(poolName + ".maxconn", "0"); int max; try { max = Integer.valueOf(maxconn).intValue(); } catch (NumberFormatException e) { log("错误的最大连接数:" + maxconn + ".连接池" + poolName); max = 0; } DBConnectionPool pool = new DBConnectionPool(poolName, url, user, password, max); pools.put(poolName, pool); log("成功创建连接池" + poolName); } } } private void init() { InputStream is = getClass().getResourceAsStream("/db.properties"); Properties dbProps = new Properties(); try { dbProps.load(is); } catch (Exception e) { System.err.println("不能读取属性文件。请确保db.properties在你的CLASSPATH中"); return; } String logFile = dbProps.getProperty("logfile", "DBConnectionManager.log"); try { log = new PrintWriter(new FileWriter(logFile, true), true); } catch (IOException e) { System.err.println("无法打开日志文件:" + logFile); log = new PrintWriter(System.err); } loadDriver(dbProps); createPools(dbProps); } private void loadDriver(Properties props) { String driverClasses = props.getProperty("drivers"); StringTokenizer st = new StringTokenizer(driverClasses); while (st.hasMoreElements()) { String driverClassName = st.nextToken().trim(); try { Driver driver = (Driver) Class.forName(driverClassName) .newInstance(); DriverManager.registerDriver(driver); drivers.addElement(driver); log("成功注册驱动程序" + driverClassName); } catch (Exception e) { log("无法注册驱动程序:" + driverClassName + ",错误" + e); } } } private void log(String msg) { log.println(new Date() + ":" + msg); } private void log(Throwable e, String msg) { log.println(new Date() + ":" + msg); e.printStackTrace(log); } // 建立DBConnectionPool内部类 class DBConnectionPool { private int checkOut; private Vector freeConnections = new Vector(); private int maxconn; private String name; private String password; private String URL; private String user; public DBConnectionPool(String name, String URL, String user, String password, int maxconn) { this.name = name; this.URL = URL; this.password = password; this.user = user; this.maxconn = maxconn; } public synchronized void freeConnection(Connection con) { freeConnections.addElement(con); checkOut--; notifyAll(); } public synchronized Connection getConnection() { Connection con = null; if (freeConnections.size() > 0) { con = (Connection) freeConnections.firstElement(); freeConnections.removeElementAt(0); try { if (con.isClosed()) { log("从连接池" + name + "删除一个连接"); con = getConnection(); } } catch (SQLException e) { log("从连接池" + name + "删除一个连接"); con = getConnection(); } } else if (maxconn == 0 || checkOut < maxconn) { con = newConnection(); } if (con != null) { checkOut++; } return con; } public synchronized Connection getConnection(long timeout) { long startTime = new Date().getTime(); Connection con; while ((con = getConnection()) == null) { try { wait(timeout); } catch (InterruptedException e) { } if ((new Date().getTime() - startTime) >= timeout) { return null; } } return con; } public void release() { Enumeration allConnections = freeConnections.elements(); while (allConnections.hasMoreElements()) { Connection con = (Connection) allConnections.nextElement(); try { con.close(); log("关闭连接池" + name + "中的连接"); } catch (SQLException e) { log(e, "无法关闭连接池" + name + "中的连接"); } } freeConnections.removeAllElements(); } private Connection newConnection() { Connection con = null; try { con = DriverManager.getConnection(URL, user, password); log("连接池" + name + "创建一个新的连接"); } catch (SQLException e) { log(e, "无法创建下列URL的连接" + URL); return null; } return con; } } }

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档