jdbc数据源

数据源设计思想和数据库连接池设计思想基本相似。大家知道在操作数据库程序时,创建连接所占用时间最多,为了提高程序的效率,便出现了数据库连接池技术。

                  数据库连接池实现原理:在系统启动时便创建一定数量连接,将它们放在线程安全的集合中(这便称为数据库连接池),当某段程序要连接数据库时,不必再去创建连接而直接去从池中去取,这样也就减少了创建连接时间。在关闭连接时,也不是真正关闭而是将其重新放回池中。从而提高系统效能。

一下说我最近写的一个数据源类,仅供大家参考:

package dataSource;

import java.io.File;
import java.io.InputStream;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;


public class DataSource implements javax.sql.DataSource{
	/**驱动*/
	private String driver;
	/**url*/
	private String url;
	/**用户名*/
	private String user;
	/**密码*/
	private String password;
	/**初始化连接数*/
	private int initCount;
	/**连接池中最大连接数*/
	private int maxCount;
	/**当前使用连接数*/
	private int currentCount=0;
	/**等待连接最长时间*/
	private int wait=3000;
	/**输出日志流*/
	private PrintWriter out;
	/**连接池*/
	private Vector<ConnectionPool> connections;
	
	public DataSource(){
		init();
		initConnections();
	}
	/**
	 * 初始化
	 */
	private void init(){
		Properties prop=new Properties();
		try {
			InputStream input=DataSource.class.getClassLoader().getResourceAsStream("dataSource.properties");
			prop.load(input);
			driver=prop.getProperty("driver");
			Class.forName(driver);//加载驱动
			url=prop.getProperty("url");
			user=prop.getProperty("user");
			password=prop.getProperty("password");
			String itCount=prop.getProperty("initCount");
			initCount=itCount==null?1:Integer.parseInt(itCount);
			String mCount=prop.getProperty("maxCount");
			maxCount=mCount==null?1:Integer.parseInt(mCount);
			connections=new Vector<ConnectionPool>();
			out=new PrintWriter(new File("c:/datasouce.log"),"UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
			writerLog(e.getMessage());
			throw new RuntimeException("装载配置文件错误");
		}
	}
	/**
	 * 初始化连接池中数据库连接个数
	 *
	 */
	private void initConnections(){
		for(int i=0;i<initCount;i++){
			try {
				Connection conn=createConnection();
				if(i==0){
					DatabaseMetaData metaData=conn.getMetaData();
					int dataCount=metaData.getMaxConnections();
					writerLog("数据库最大连接数为:"+dataCount);
					if(dataCount>0&&maxCount>dataCount){
						maxCount=dataCount;
					}
				}
				ConnectionPool pool=new ConnectionPool(conn);
				connections.addElement(pool);
			} catch (SQLException e) {
				e.printStackTrace();
				writerLog(e.getMessage());
				throw new RuntimeException("初始化连接池错误");
			}
		}
	}
	/**
	 * 创建连接对象
	 * @return 创建好的连接对象
	 * @throws SQLException
	 */
	private Connection createConnection() throws SQLException{
		 currentCount++;
		 writerLog("当前正在使用连接数:"+currentCount);
		return DriverManager.getConnection(url,user,password);
	}
	/**
	 * 当数据源中原有连接已用完时,就创建一个新的数据库连接对象到连接池中
	 * 且这个连接需要时才被创建,一旦创建就被使用
	 * @return
	 * @throws SQLException
	 */
	private ConnectionPool createConnPool() throws SQLException{
		Connection conn=createConnection();
		ConnectionPool pool=new ConnectionPool(conn);
		pool.setBusy(true);
		writerLog("添加一个新的数据库连接对象到连接池中");
		return pool;
	}
	/**
	 * 从连接池中得到连接对象
	 */
	public synchronized Connection getConnection() throws SQLException {
		if(connections==null){
			writerLog("连接池已不存在");
			return null;
		}
		Connection conn=findFreeConnection();
		if(conn==null){
		  if(currentCount<=maxCount){
			  ConnectionPool conn1=createConnPool();
			  return conn1.getConn();
			}else{
				try {
					writerLog("正在等待数据库连接 ....");
					Thread.sleep(wait);
					return findFreeConnection();
				} catch (InterruptedException e) {
					writerLog(e.getMessage());
					e.printStackTrace();
				}
			}
		}
		return conn;
	}
	/**
	 * 查找当前连接池中还有没有空闲连接
	 * @return Connection
	 */
	private Connection findFreeConnection(){
		Connection conn=null;
		if(connections.size()>0){
			Enumeration enu=connections.elements();
			while(enu.hasMoreElements()){
				ConnectionPool pool=(ConnectionPool)enu.nextElement();
				if(!(pool.isBusy())){
					conn=pool.getConn();
					pool.setBusy(true);
					writerLog("找到一个空闲连接");
					return conn;
				}
				
			}
		}
		return conn;
	}
	/**
	 * 关闭连接对象(实际上并不是真正的关闭,而是将其状态置为空闲)
	 * @param conn 要关闭连接对象
	 */
	public synchronized void closeConnection(Connection conn){
		currentCount--;
		if(connections.size()==0||connections==null){
			writerLog("连接池已不存在");
			return;
		}
		Enumeration enu=connections.elements();
		while(enu.hasMoreElements()){
			ConnectionPool pool=(ConnectionPool)enu.nextElement();
			if(pool.getConn()==conn){
				pool.setBusy(false);
				writerLog("关闭了当前连接");
				break;
			}
		}
		out.close();
	}
	/**
	 * 单独创建一个连接,不从连接池中去取
	 */
	public synchronized Connection getConnection(String username, String password)throws SQLException {
		writerLog("创建一个独立于连接池的连接对象");
		return DriverManager.getConnection(url,username,password);
	}
	/**
	 * 获得日志输出流
	 */
	public PrintWriter getLogWriter() throws SQLException {
		return out;
	}
	/**
	 * 设置日志输出流
	 */
	public void setLogWriter(PrintWriter out) throws SQLException {
		this.out=out;
	}
	/**
	 * 如果当前没有可用连接,设置等待时间 毫秒数
	 */
	public void setLoginTimeout(int seconds) throws SQLException {
		this.wait=seconds;
	}
	/**
	 * 或得系统等待连接时间
	 */
	public int getLoginTimeout() throws SQLException {
		return wait;
	}
	
	private void writerLog(String errMessage){
		out.append("#=========================================#\n");
		out.append(errMessage+"\n");
		out.append("#=========================================#\n");
	}
	
	/**
	 * 包装到连接池的连接对象
	 * @author newapps
	 */
	class ConnectionPool{
		/**当前数据库创建连接*/
		Connection conn;
		/**当前连接是否处于工作状态*/
		boolean busy=false;
		/**构造函数*/
		ConnectionPool(Connection conn){
			this.conn=conn;
		}
		void setBusy(boolean busy){
			this.busy=busy;
		}
		boolean isBusy(){
			return busy;
		}
		void setConn(Connection conn){
			this.conn=conn;
		}
		Connection getConn(){
			return conn;
		}
	}
}

配置文件(dateSource.properties)

#===================================================================================
#各种常用数据库驱动名称
#============mysql Driver====================
#com.mysql.jdbc.Driver
#============oracle Driver===================
#oracle.jdbc.driver.OracleDriver
#============pointbase Driver================
#com.pointbase.jdbc.jdbcUniversalDriver
#============SQL Server Driver===============
#com.microsoft.jdbc.sqlserver.SQLServerDriver
#============DB2 Driver======================
#com.ibm.db2.jdbc.app.DB2Driver
#===================================================================================
#数据库连接url格式为:"jdbc:子协议:子协议名称//主机名:端口号/数据库名?属性名=属性值&属性名=属性值"
#dbUser和dbPassword也可以通过:属性名=属性值方式传入。
#设置数据库的编码格式:useUnicode=true&characterEncoding=GBK
#============mysql url==============================================================
#jdbc:mysql://<machine_name><:port>/dbname
#端口号:默认是 3306
#============oracle url=============================================================
#jdbc:oracle:thin:@<machine_name><:port>:dbname
#端口号:默认是 1521
#============pointbase url==========================================================
#jdbc:pointbase:server://<machine_name><:port>/dbname
#端口号:默认是 9092
#============SQL Server url=========================================================
#jdbc:microsoft:sqlserver://<machine_name><:port>;DatabaseName=<dbname>
#端口号:默认是 1433
#============DB2 url================================================================
#jdbc:db2://<machine_name><:port>/dbname
#端口号:默认是 5000
#===================================================================================
#数据库驱动
driver=com.mysql.jdbc.Driver
#数据库URL
url=jdbc:mysql://127.0.0.1:3306/ajax
#连接数据库用户
user=root
#连接数据库密码
password=123
#初始化连接数
initCount=1
#连接池中最大连接数
maxCount=50

相关推荐