数据库连接池技术

要下班了,先把代码贴上来,明天有时间来加说明。
package com;

import java.io.Serializable;

public class ConnectionParam implements Serializable {
    
private String driver; // 数据库驱动程序

    
private String url; // 数据连接的URL

    
private String user; // 数据库用户名

    
private String password; // 数据库密码

    
private int minConnection = 0// 初始化连接数

    
private int maxConnection = 50// 最大连接数

    
private long timeoutValue = 600000;// 连接的最大空闲时间

    
private long waitTime = 30000// 取连接的时候如果没有可用连接最大的等待时间

    
public ConnectionParam(String driver, String url, String user,
            String password) 
{
        
super();
        
this.driver = driver;
        
this.password = password;
        
this.url = url;
        
this.user = user;
    }


    
public String getDriver() {
        
return driver;
    }


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


    
public int getMaxConnection() {
        
return maxConnection;
    }


    
public void setMaxConnection(int maxConnection) {
        
this.maxConnection = maxConnection;
    }


    
public int getMinConnection() {
        
return minConnection;
    }


    
public void setMinConnection(int minConnection) {
        
this.minConnection = minConnection;
    }


    
public String getPassword() {
        
return password;
    }


    
public void setPassword(String password) {
        
this.password = password;
    }


    
public long getTimeoutValue() {
        
return timeoutValue;
    }


    
public void setTimeoutValue(long timeoutValue) {
        
this.timeoutValue = timeoutValue;
    }


    
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 long getWaitTime() {
        
return waitTime;
    }


    
public void setWaitTime(long waitTime) {
        
this.waitTime = waitTime;
    }


}

DataSourceImpl类:
package com;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import javax.sql.DataSource;

public class DataSourceImpl implements DataSource {

    
private ConnectionParam param ;
    
private Connection conn ;
    
    
public void initConnection(){
        
try{
            Class.forName(param.getDriver());
            conn 
= DriverManager.getConnection(param.getUrl(),param.getUser(),param.getPassword());
        }
catch(Exception e){}
    }


    
public void stop() {

    }


    
public void close() {

    }


    
public DataSourceImpl(ConnectionParam param) {
        
this.param = param;
    }


    
public Connection getConnection() throws SQLException {
        
return conn;
    }


    
public Connection getConnection(String username, String password)
            
throws SQLException {
        
// TODO Auto-generated method stub
        return null;
    }


    
public PrintWriter getLogWriter() throws SQLException {
        
// TODO Auto-generated method stub
        return null;
    }


    
public void setLogWriter(PrintWriter out) throws SQLException {
        
// TODO Auto-generated method stub

    }


    
public void setLoginTimeout(int seconds) throws SQLException {
        
// TODO Auto-generated method stub

    }


    
public int getLoginTimeout() throws SQLException {
        
// TODO Auto-generated method stub
        return 0;
    }


    
public Object unwrap(Class arg0) throws SQLException {
        
// TODO Auto-generated method stub
        return null;
    }


    
public boolean isWrapperFor(Class arg0) throws SQLException {
        
// TODO Auto-generated method stub
        return false;
    }


}

代理接管连接关闭(Connection.close())的类_Connection:
package com;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;

public class _Connection implements InvocationHandler {

    
private final static String CLOSE_METHOD_NAME = "close";

    
private Connection conn = null;

    
// 数据库的忙状态
    private boolean inUse = false;

    
// 用户最后一次访问该连接方法的时间
    private long lastAccessTime = System.currentTimeMillis();

    _Connection(Connection conn, 
boolean inUse) {
        
this.conn = conn;
        
this.inUse = inUse;
    }


    
/**
     * Returns the conn.
     * 
     * 
@return Connection
     
*/

    
public Connection getConnection() {
        
// 返回数据库连接conn的接管类,以便截住close方法
        Connection conn2 = (Connection) Proxy.newProxyInstance(conn.getClass()
                .getClassLoader(), conn.getClass().getInterfaces(), 
this);
        
return conn2;
    }


    
/**
     * 该方法真正的关闭了数据库的连接
     * 
     * 
@throws SQLException
     
*/

    
void close() throws SQLException {
        
// 由于类属性conn是没有被接管的连接,因此一旦调用close方法后就直接关闭连接
        conn.close();
    }


    
/**
     * Returns the inUse.
     * 
     * 
@return boolean
     
*/

    
public boolean isInUse() {
        
return inUse;
    }


    
/**
     * 
@see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
     *      java.lang.reflect.Method, java.lang.Object)
     
*/

    
public Object invoke(Object proxy, Method m, Object[] args)
            
throws Throwable {
        Object obj 
= null;
        
// 判断是否调用了close的方法,如果调用close方法则把连接置为无用状态
        if (CLOSE_METHOD_NAME.equals(m.getName()))
            setInUse(
false);
        
else
            obj 
= m.invoke(conn, args);
        
// 设置最后一次访问时间,以便及时清除超时的连接
        lastAccessTime = System.currentTimeMillis();
        
return obj;
    }


    
/**
     * Returns the lastAccessTime.
     * 
     * 
@return long
     
*/

    
public long getLastAccessTime() {
        
return lastAccessTime;
    }


    
/**
     * Sets the inUse.
     * 
     * 
@param inUse
     *            The inUse to set
     
*/

    
public void setInUse(boolean inUse) {
        
this.inUse = inUse;
    }


}

连接池管理类ConnectionFactory:
package com;

import java.sql.SQLException;
import java.util.Hashtable;

import javax.naming.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.sql.DataSource;

/**
 * 连接池类厂,该类常用来保存多个数据源名称合数据库连接池对应的哈希
 * 
@author liusoft
 
*/

public class ConnectionFactory
{
    
//该哈希表用来保存数据源名和连接池对象的关系表
    static Hashtable connectionPools = null;
    
static{
        connectionPools 
= new Hashtable(2,0.75F);
    }
 
    
/**
     * 从连接池工厂中获取指定名称对应的连接池对象
     * 
@param dataSource    连接池对象对应的名称
     * 
@return DataSource    返回名称对应的连接池对象
     * 
@throws NameNotFoundException    无法找到指定的连接池
     
*/

    
public static DataSource lookup(String dataSource) 
        
throws NameNotFoundException
    
{
        Object ds 
= null;
        ds 
= connectionPools.get(dataSource);
        
if(ds == null || !(ds instanceof DataSource))
            
throw new NameNotFoundException(dataSource);
        
return (DataSource)ds;
    }

    
/**
     * 将指定的名字和数据库连接配置绑定在一起并初始化数据库连接池
     * 
@param name        对应连接池的名称
     * 
@param param    连接池的配置参数,具体请见类ConnectionParam
     * 
@return DataSource    如果绑定成功后返回连接池对象
     * 
@throws NameAlreadyBoundException    一定名字name已经绑定则抛出该异常
     * 
@throws ClassNotFoundException        无法找到连接池的配置中的驱动程序类
     * 
@throws IllegalAccessException        连接池配置中的驱动程序类有误
     * 
@throws InstantiationException        无法实例化驱动程序类
     * 
@throws SQLException                无法正常连接指定的数据库
     
*/

    
public static DataSource bind(String name, ConnectionParam param)
        
throws NameAlreadyBoundException,ClassNotFoundException,
                IllegalAccessException,InstantiationException,SQLException
    
{
        DataSourceImpl source 
= null;
        
try{
            lookup(name);
            
throw new NameAlreadyBoundException(name);
        }
catch(NameNotFoundException e){
            source 
= new DataSourceImpl(param);
            source.initConnection(); 
            connectionPools.put(name, source);
        }

        
return source;
    }

    
/**
     * 重新绑定数据库连接池
     * 
@param name        对应连接池的名称
     * 
@param param    连接池的配置参数,具体请见类ConnectionParam
     * 
@return DataSource    如果绑定成功后返回连接池对象
     * 
@throws NameAlreadyBoundException    一定名字name已经绑定则抛出该异常
     * 
@throws ClassNotFoundException        无法找到连接池的配置中的驱动程序类
     * 
@throws IllegalAccessException        连接池配置中的驱动程序类有误
     * 
@throws InstantiationException        无法实例化驱动程序类
     * 
@throws SQLException                无法正常连接指定的数据库
     
*/

    
public static DataSource rebind(String name, ConnectionParam param)
        
throws NameAlreadyBoundException,ClassNotFoundException,
                IllegalAccessException,InstantiationException,SQLException
    
{
        
try{
            unbind(name);
        }
catch(Exception e){}
        
return bind(name, param);
    }

    
/**
     * 删除一个数据库连接池对象
     * 
@param name
     * 
@throws NameNotFoundException
     
*/

    
public static void unbind(String name) throws NameNotFoundException
    
{
        DataSource dataSource 
= lookup(name);
        
if(dataSource instanceof DataSourceImpl){
            DataSourceImpl dsi 
= (DataSourceImpl)dataSource;
            
try{
                dsi.stop();
                dsi.close();
            }
catch(Exception e){
            }
finally{
                dsi 
= null;
            }

        }

        connectionPools.remove(name);
    }

    
}


测试主类:
package com;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import javax.sql.DataSource;

public class test {

    
public static void main(String[] args) throws Exception {
        String name 
= "poolA";
        String driver 
= "oracle.jdbc.driver.OracleDriver";
        String url 
= "jdbc:oracle:thin:@127.0.0.1:1521:orcl";
        ConnectionParam param 
= new ConnectionParam(driver, url, "zqbchina",
                
"password");
        param.setMinConnection(
1);
        param.setMaxConnection(
5);
        param.setTimeoutValue(
20000);
        ConnectionFactory.bind(name, param);
        System.out.println(
"bind datasource ok.");
        
// 以上代码是用来登记一个连接池对象,该操作可以在程序初始化只做一次即可
        
// 以下开始就是使用者真正需要写的代码
        DataSource ds = ConnectionFactory.lookup(name);
        String sql 
= "select name from tablea";
        _Connection _conn 
= null;
        
try {
            
for (int i = 0; i < 10; i++{
                Connection conn 
=  ds.getConnection();
                _conn 
= new _Connection(conn,false);
                conn 
= _conn.getConnection();
                
try {
                    testSQL(conn, sql);
                }
 finally {
                    
try {
                        conn.close();
                    }
 catch (Exception e) {
                    }

                }

            }

        }
 catch (Exception e) {
            e.printStackTrace();
        }
 finally {
            ConnectionFactory.unbind(name);
            System.out.println(
"unbind datasource ok.");
            System.exit(
0);
        }


    }


    
public static void testSQL(Connection conn, String sql) throws Exception {
        PreparedStatement ps 
= conn.prepareStatement(sql);
        ResultSet rs 
= ps.executeQuery();
        
while (rs.next())
            System.out.println(rs.getString(
1));
    }


}

ok。

posted on 2007-09-18 18:12 心砚 阅读(472) 评论(0)  编辑  收藏 所属分类: Java


只有注册用户登录后才能发表评论。


网站导航:
 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(2)

随笔分类

文章分类

文章档案

Forum

搜索

最新评论

阅读排行榜

评论排行榜