博客开张,把自己的一些经验做点记录.
朋友的在维护一个老的内部网站系统,数据库使用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数据库文件方式获取数据源呢.
分享到:
相关推荐
Apache Commons Pool是Java的对象池设计模式实现,它提供了一种管理资源的机制,可以有效地复用昂贵的资源,比如数据库连接、线程或者大对象。对象池的主要功能包括: - **对象池化(Object Pooling)**: 创建并...
- 更推荐使用JDBC直接支持的数据库驱动,例如,对于较新的Access版本,可以尝试使用Apache的`org.apache.commons.dbcp2`库,它提供了对JDBC的更高效和稳定的连接池管理。 - 不要在生产环境中使用空的用户名和密码...
这个例子展示了如何利用Apache Commons Pool2创建一个OSS连接池,并将其与Spring框架集成。通过Spring的依赖注入,我们可以方便地在应用中使用这些配置好的连接池。在实际项目中,可以根据需求调整`...
在JNDI环境中,它可能与DBCP一起使用,帮助实现数据库连接池的底层管理。 4. `tomcat-jni.jar`:这是Tomcat服务器的一部分,提供了本地接口(JNI)支持,用于提高服务器的性能。在配置JNDI数据源时,Tomcat-JNI可能...
虽然它本身不是专门为数据库连接池设计的,但Commons-DBCP使用了Commons-Pool来实现数据库连接的池化。通过对象池,可以有效地复用对象,减少创建和销毁对象的开销,提高系统效率。 在初学者的学习过程中,理解这些...
在基于Eclipse的环境中实现Struts与数据库的连接池,是Web开发中的常见任务,可以提升应用程序的性能和资源利用率。本文将详细介绍如何在Eclipse中通过Struts配置数据源,实现与数据库的池连接。 首先,我们需要...
DBCP(Apache Commons DBCP)是Apache提供的一个开源的数据库连接池组件,它实现了数据源接口,可以有效管理数据库连接,提高系统性能。DBCP提供以下功能: 1. **连接池管理**:维护一定数量的数据库连接,复用这些...
5. `commons-pool.jar`:Apache Commons Pool是对象池化的实现,DBCP依赖此库来管理连接池中的数据库连接。 6. `mysql.properties`:这是一个配置文件,可能包含了连接MySQL数据库所需的参数,如URL、用户名、密码...
5. **commons-dbcp.jar**:Apache Commons DBCP是Apache的一个数据库连接池组件,它提供了一种有效管理和重用数据库连接的方式,提高了系统的性能和效率。在Spring中,DBCP可以配合DataSource一起使用,实现数据库...
Spring无法加载指定的c3p0连接池数据源类,原因是项目中未包含c3p0.jar。从官方源下载c3p0库并将其添加到项目类路径中,确保版本与项目需求一致。 7. **The Network Adapter could not establish the connection ...
3. **commons-dbcp-1.2.jar**:Apache Commons DBCP(Database Connection Pooling)是一个数据库连接池实现。在Spring应用中,数据库连接池可以有效地管理和复用数据库连接,减少创建和关闭连接的开销,提高应用...
4. **commons-dbcp.jar**:Apache Commons DBCP是基于Jakarta-DBCP的一个数据库连接池组件,提供数据库连接的管理与复用,提高数据库操作的性能。在Dz_Model工具中,可能是用来管理和优化数据库连接,确保生成DAO时...
- `commons-dbcp-1.3.jar`和`commons-pool-1.5.4.jar`:Apache Commons的数据库连接池组件,提高数据库连接的复用效率。 通过以上介绍,我们对NutMvc框架有了更深入的理解。它在Java Web开发中提供了灵活、高效的...
8. **DBCP (Database Connection Pool)**:这是一个数据库连接池,如Apache Commons DBCP,它管理数据库连接,提高性能并优化资源利用。在Spring中,通过配置DBCP,可以实现数据库连接的池化,提升系统性能。 以上...
5. **tomcat-dbcp.jar**:Apache Tomcat的数据库连接池(Database Connection Pool)实现,管理数据库连接,提高应用性能。DBCP允许应用在需要时获取数据库连接,使用完毕后归还,避免频繁创建和销毁连接带来的开销...
此外,还需要配置`LdapContextSource`以创建连接池,以及`LdapTemplate`实例以供应用程序使用。 5. Spring LDAP与Spring Framework集成: Spring LDAP很好地融入了Spring生态,可以与其他Spring模块(如Spring ...
例如,Apache Commons Pool库可以用来实现这个功能。在Shiro配置中,可以通过设置`ldapContextFactory`的`connectionPoolEnabled`为`true`来启用连接池。 **查询优化** 在处理大量用户或复杂权限结构时,有效的...
综合以上信息,这个项目是一个基础的Web管理系统,它展示了如何在Java Web应用中使用JSP、Servlet、DAO、VO和DBCP来实现数据库管理功能。通过学习和实践这样的项目,开发者可以提升自己在Java后端开发、数据库操作和...