`
maxima
  • 浏览: 2377 次
  • 来自: ...
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

用apache.commons.pool 实现Access数据库连接池

    博客分类:
  • java
阅读更多

博客开张,把自己的一些经验做点记录.

朋友的在维护一个老的内部网站系统,数据库使用access,该系统访问量一多经常会报sql错误,提示客户端过多问题.

查看了系统代码,发现这个系统的数据库连接代码每次都是重新创建的.

    public static Connection getConn() throws ClassNotFoundException,
            SQLException {
        Connection conn = null;
        String driver = "jdbc:odbc:driver={microsoft access driver (*.mdb)};dbq=d:\\data.mdb";
               Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");   
        conn = DriverManager.getConnection(driver);
        return conn;
    }

 这样的问题就很严重,首先就是无法控制并发的数据库操作,导致并发高于一定量后access数据库直接报错提示客户端过多。

其次就是数据库操作效率低下,每次建立连接和释放连接的效率很低。

解决这个问题需要对数据库连接上加入连接池,保证数据库连接安全可控,高效。

由于是老系统要求改动的代码尽量少,google了一把也没找到可以直接使用access文件作为数据库连接池的代码,就自己动手写了一个。

该连接池只要依赖apache.commons.pool 开源组件。

首先实现一个数据库连接创建,销毁的工厂类DBConnectFactory该类实现了接口org.apache.commons.pool.PoolableObjectFactory

package base;

import java.sql.Connection;
import java.sql.DriverManager;

import org.apache.commons.pool.PoolableObjectFactory;

/**
 * 数据库连接工厂类
 *
 * @author binda.mabd
 * @version 1.0
 * @date 2009-4-3
 */
public class DBConnectFactory implements PoolableObjectFactory {
	private int count =0 ;
	private String driver ;
	private String className;
	public DBConnectFactory(String className,String driver){
		this.className = className;
		this.driver = driver;
	}
	/**
	 * 对象初始化后加入池的时候使用,设置对象为可用状态。
	 */
	public void activateObject(Object arg0) throws Exception {
	//直接加入
		
	}
	/**
	 * 对象销毁方法
	 */
	public void destroyObject(Object arg0) throws Exception {
		 System.err.println("destroyObject Object " + arg0.getClass().getName());
		if(arg0!=null){
			Connection con = (Connection)arg0;
			try{
			con.close();
			 count --;
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	/**
	 * 对象创建方法
	 */
	public Object makeObject() throws Exception {
		try {
			Class.forName(className);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}  
		  count ++;
		   return  DriverManager.getConnection(driver);

	}
	/**
	 * 非创建对象回到池的时使用,设置对象为可用.
	 */
	public void passivateObject(Object arg0) throws Exception {
		Connection con = (Connection)arg0;
		//如果非自动commit类型连接,强制comit后返回连接池
		if(!con.getAutoCommit()){
			con.commit();
		}

	}
	/**
	 * 状态检查对象是否可用
	 */
	public boolean validateObject(Object arg0) {
		
		try{
		Connection con = (Connection)arg0;
		return con!=null&&!con.isClosed();
		}catch(Exception e){
		return false ;
		}
				
	}

}

 

 

 

有了DBConnectFactory工厂类,就可以通过org.apache.commons.pool.impl.GenericObijectPool 来创建一个自定义的连接池.

package base;

import java.sql.Connection;

import org.apache.commons.pool.PoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;

public class SimpleAccessPool {
	
    GenericObjectPool pool  = null; 
    PoolableObjectFactory factory = null;
    public SimpleAccessPool (String accessFilePath){
		  String className = "sun.jdbc.odbc.JdbcOdbcDriver"	;
		  String driver = "jdbc:odbc:driver={microsoft access driver (*.mdb)};dbq=";
		  driver = driver + accessFilePath;
    	factory = new DBConnectFactory(className,driver);
    	
    }
    public void init(){
        pool = new GenericObjectPool(factory);
        //最大连接数
         pool.setMaxActive(30); 
         //最大空闲连接数
         pool.setMaxIdle(20);
              //连接等待1分钟
         pool.setMaxWait(60000);
    }
    /** 获得连接*/
     public Connection getConnection() {
    	try {
			return	(Connection) pool.borrowObject();
			
		}catch (Exception e){
			 e.printStackTrace();
				throw new RuntimeException("get connect error",e);
		}
    	
     }
     /**释放连接*/
     public void relaseConnection(Connection con){
         try {
			pool.returnObject(con);
		} catch (Exception e) {
			  e.printStackTrace();
			throw new RuntimeException("relase connect error",e);
		}
     }
	
	}

 写了一个测试类Main,并发1000个数据库查询请求

package base;

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




public class DBTest {
	
	static SimpleAccessPool connPoll = null ;

	public static void main(String[] args) {
		 String  current_mdb_path = "D:\\data.mdb";
		 connPoll = new SimpleAccessPool(current_mdb_path);
		 connPoll.init();
		 for(int i=0;i<1000;i++){
			 Thread run = new Thread(new TestRun(i+""));
			 run.start();
		 }
	}

}

/** 
 *并发测试考虑实现runable
 * */
class TestRun implements Runnable{
	   private String id ;
	 
	   public TestRun(String id){
		   this.id = id;
	   }
		public void run() {
		  Connection conn =DBTest.connPoll.getConnection();
		  long t = System.currentTimeMillis();
	   	  PreparedStatement pstmt = null;
	      ResultSet rs  = null ;
	         String sql_delele = "select * from news where news_id <?";
	         try {
	             pstmt = conn.prepareStatement(sql_delele);
	             pstmt.setInt(1,100);
	             rs = pstmt.executeQuery();
	         } catch (SQLException ex) {
	             ex.printStackTrace();
	         }
	         try{
	        	 rs.close();
	        	 pstmt.close();
	         }catch (SQLException ex) {
	             ex.printStackTrace();
	         }
	         DBTest.connPoll.relaseConnection(conn);
	     	System.out.println("ok!cost time ms:"+(System.currentTimeMillis()-t));
		}
		
	}

 

好了,一个简单的数据库连接池ok了.

遇到的疑问:

数据库连接Connection重复使用是否会有什么状态上的问题, 在回收的池的时候有什么方法把连接的状态初始化.我代码中做了一个检查,回收Connection时如果非自动commit连接则强制commit 避免重复使用connection事务回滚错误.

开源的连接池框架没有研究过,是否能支持直接读取Access数据库文件方式获取数据源呢.

 

 

3
0
分享到:
评论
1 楼 matraxa 2010-11-16  
你好,想请问下,如果我在一个jsp页面触发一servelt,在servelt里使用了这样的语句:
String  current_mdb_path = "D:\\data.mdb";   
         connPoll = new SimpleAccessPool(current_mdb_path);   
         connPoll.init();
          PreparedStatement pstmt = null;   
          ResultSet rs  = null ;   
         String sql_delele = "select * from news where news_id<?";   
                 pstmt = conn.prepareStatement(sql_delele);   
                 pstmt.setInt(1,100);   
                 rs = pstmt.executeQuery(); 

请问如果这样。能发挥数据库池的效果吗?
如果我把这个开启数据库的代码
String  current_mdb_path = "D:\\data.mdb";   
         connPoll = new SimpleAccessPool(current_mdb_path);   
         connPoll.init();

放在index.jsp,等触发了servelt再查询
Connection conn =DBTest.connPoll.getConnection();   
          long t = System.currentTimeMillis();   
          PreparedStatement pstmt = null;   
          ResultSet rs  = null ;   
             String sql_delele = "select * from news where news_id <?";   
                 pstmt = conn.prepareStatement(sql_delele);   
                 pstmt.setInt(1,100);   
                 rs = pstmt.executeQuery();   

这样有效果吗?

相关推荐

    commons-beanutils.jar commons-collections-3.1.jar commons-pool-1.2.jar

    Apache Commons Pool是Java的对象池设计模式实现,它提供了一种管理资源的机制,可以有效地复用昂贵的资源,比如数据库连接、线程或者大对象。对象池的主要功能包括: - **对象池化(Object Pooling)**: 创建并...

    Java连接Access数据库.pdf

    - 更推荐使用JDBC直接支持的数据库驱动,例如,对于较新的Access版本,可以尝试使用Apache的`org.apache.commons.dbcp2`库,它提供了对JDBC的更高效和稳定的连接池管理。 - 不要在生产环境中使用空的用户名和密码...

    apache common pool2 实例

    这个例子展示了如何利用Apache Commons Pool2创建一个OSS连接池,并将其与Spring框架集成。通过Spring的依赖注入,我们可以方便地在应用中使用这些配置好的连接池。在实际项目中,可以根据需求调整`...

    apache jndi 组件

    在JNDI环境中,它可能与DBCP一起使用,帮助实现数据库连接池的底层管理。 4. `tomcat-jni.jar`:这是Tomcat服务器的一部分,提供了本地接口(JNI)支持,用于提高服务器的性能。在配置JNDI数据源时,Tomcat-JNI可能...

    无冲突ssh架包下载

    虽然它本身不是专门为数据库连接池设计的,但Commons-DBCP使用了Commons-Pool来实现数据库连接的池化。通过对象池,可以有效地复用对象,减少创建和销毁对象的开销,提高系统效率。 在初学者的学习过程中,理解这些...

    基于eclipse实现struts池连

    在基于Eclipse的环境中实现Struts与数据库的连接池,是Web开发中的常见任务,可以提升应用程序的性能和资源利用率。本文将详细介绍如何在Eclipse中通过Struts配置数据源,实现与数据库的池连接。 首先,我们需要...

    JDBC小组件 对DBCP连接池的封装

    DBCP(Apache Commons DBCP)是Apache提供的一个开源的数据库连接池组件,它实现了数据源接口,可以有效管理数据库连接,提高系统性能。DBCP提供以下功能: 1. **连接池管理**:维护一定数量的数据库连接,复用这些...

    Dz_Model 1.0 修正版

    5. `commons-pool.jar`:Apache Commons Pool是对象池化的实现,DBCP依赖此库来管理连接池中的数据库连接。 6. `mysql.properties`:这是一个配置文件,可能包含了连接MySQL数据库所需的参数,如URL、用户名、密码...

    spring2.5jar包.zip

    5. **commons-dbcp.jar**:Apache Commons DBCP是Apache的一个数据库连接池组件,它提供了一种有效管理和重用数据库连接的方式,提高了系统的性能和效率。在Spring中,DBCP可以配合DataSource一起使用,实现数据库...

    MyEclipse报错说明

    Spring无法加载指定的c3p0连接池数据源类,原因是项目中未包含c3p0.jar。从官方源下载c3p0库并将其添加到项目类路径中,确保版本与项目需求一致。 7. **The Network Adapter could not establish the connection ...

    spring核心jar

    3. **commons-dbcp-1.2.jar**:Apache Commons DBCP(Database Connection Pooling)是一个数据库连接池实现。在Spring应用中,数据库连接池可以有效地管理和复用数据库连接,减少创建和关闭连接的开销,提高应用...

    Dz_Model 1.0

    4. **commons-dbcp.jar**:Apache Commons DBCP是基于Jakarta-DBCP的一个数据库连接池组件,提供数据库连接的管理与复用,提高数据库操作的性能。在Dz_Model工具中,可能是用来管理和优化数据库连接,确保生成DAO时...

    nutMvc 最专业的讲解

    - `commons-dbcp-1.3.jar`和`commons-pool-1.5.4.jar`:Apache Commons的数据库连接池组件,提高数据库连接的复用效率。 通过以上介绍,我们对NutMvc框架有了更深入的理解。它在Java Web开发中提供了灵活、高效的...

    spring开发相关jar包(json,springweb,springmvc,jdbc等)

    8. **DBCP (Database Connection Pool)**:这是一个数据库连接池,如Apache Commons DBCP,它管理数据库连接,提高性能并优化资源利用。在Spring中,通过配置DBCP,可以实现数据库连接的池化,提升系统性能。 以上...

    JAVA常用jar包集合

    5. **tomcat-dbcp.jar**:Apache Tomcat的数据库连接池(Database Connection Pool)实现,管理数据库连接,提高应用性能。DBCP允许应用在需要时获取数据库连接,使用完毕后归还,避免频繁创建和销毁连接带来的开销...

    spring-ldap1.3.1

    此外,还需要配置`LdapContextSource`以创建连接池,以及`LdapTemplate`实例以供应用程序使用。 5. Spring LDAP与Spring Framework集成: Spring LDAP很好地融入了Spring生态,可以与其他Spring模块(如Spring ...

    ldap 登陆框架

    例如,Apache Commons Pool库可以用来实现这个功能。在Shiro配置中,可以通过设置`ldapContextFactory`的`connectionPoolEnabled`为`true`来启用连接池。 **查询优化** 在处理大量用户或复杂权限结构时,有效的...

    test_JSP_ManagementSystem

    综合以上信息,这个项目是一个基础的Web管理系统,它展示了如何在Java Web应用中使用JSP、Servlet、DAO、VO和DBCP来实现数据库管理功能。通过学习和实践这样的项目,开发者可以提升自己在Java后端开发、数据库操作和...

Global site tag (gtag.js) - Google Analytics