我现在想做一个连接池,不想使用server.xml配置的容器级别的连接池。
只想做一个针对应用的连接池。
所以使用了DBCP来构建一个BasicDataSource。
主要是测试MinEvictableIdleTimeMillis出了意想之外的结果。我在以下时间创建了basicDataSource,并设置了MinEvictableIdleTimeMillis的时间为60000,即1分钟。
ds.setMinEvictableIdleTimeMillis(Long.parseLong(minEvictableIdleTimeMillis));[02:41:41,375] [ExampleAction,33] -
connection return max time is -1
connection return max idle is 8
connection return max active is 8
connection return min Idle is 0
  min connection idle time is 60000并在以下时段使用了这个datasource产生的connection.hashcode为24968504
按道理这个空闲的connection在1分钟后会自动被销毁.但是没有。[02:42:12,265] [ExampleAction,33]
 dataSource hashCode is 22958990
 active num is 0
 idle num is 1
 connection hashcode is 24968504我在经过4分钟后又执行了一次connection,发现connection的hashCode不变,如果是新的connection
hashCode会不一样才对。[02:47:58,062] [ExampleAction,33]
 dataSource hashCode is 22958990
 active num is 0
 idle num is 1
 connection hashcode is 24968504 以下是我的代码:
 BasicDataSourceHolder.java
---------------------------------------------------------------
 package com.dolphin.manager.example.dao.impl;import javax.sql.DataSource;import org.apache.commons.dbcp.BasicDataSource;import com.noname.framework.util.config.Config;public class BasicDataSourceHolder { public static DataSource dataSource;

public static DataSource createDataSource() {

String driverClass=Config.getProperty("database.jdbc.driver");
String dburl=Config.getProperty("database1.connetion.url");
String dbname=Config.getProperty("database1.connetion.user");
String dbpass=Config.getProperty("database1.connetion.password");
String maxWait=Config.getProperty("dataSource.connection.maxWait");
String maxIdle=Config.getProperty("dataSource.connection.maxIdle");
String maxActive=Config.getProperty("dataSource.connection.maxActive");
String minIdle=Config.getProperty("dataSource.connection.minIdle");
String minEvictableIdleTimeMillis=Config.getProperty("dataSource.connection.minEvictableIdleTimeMillis");

BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName(driverClass);
        ds.setUsername(dbname);
        ds.setPassword(dbpass);
        ds.setUrl(dburl);
        ds.setMaxWait(Long.parseLong(maxWait));
        ds.setMaxIdle(Integer.parseInt(maxIdle));
        ds.setMaxActive(Integer.parseInt(maxActive));
        ds.setMinIdle(Integer.parseInt(minIdle));
        ds.setMinEvictableIdleTimeMillis(Long.parseLong(minEvictableIdleTimeMillis));
        
        System.out.println("connection return max time is "+ds.getMaxWait());
        System.out.println("connection return max idle is "+ds.getMaxIdle());
        System.out.println("connection return max active is "+ds.getMaxActive());
        System.out.println("connection return min Idle is "+ds.getMinIdle());
        System.out.println("  min connection idle time is "+ds.getMinEvictableIdleTimeMillis());
        
        
        return ds;
} public static DataSource getDataSource() {
if(dataSource==null){
dataSource=createDataSource();
}
System.out.println(" dataSource hashCode is "+dataSource.hashCode());
System.out.println(" active num is "+((BasicDataSource)dataSource).getNumActive());
System.out.println(" idle num is "+((BasicDataSource)dataSource).getNumIdle());

return dataSource;
} public static void setDataSource(DataSource dataSource) {
BasicDataSourceHolder.dataSource = dataSource;
}


}BasicDataSourceFactory
----------------------------------
package com.dolphin.manager.example.dao.impl;import java.sql.Connection;
import java.sql.SQLException;
import com.noname.framework.dao.PersistentException;public class BasicDataSourceFactory { public static Connection getBasicDataSourceConnection() throws PersistentException{
Connection connection=null;
try{
connection=BasicDataSourceHolder.getDataSource().getConnection();

}catch(SQLException sql){
throw new PersistentException("Can't get BasicDataSource connection," +
"make sure your configure is right..",sql);
}
System.out.println(" connection hashcode is "+connection.hashCode());
return connection;
}
}请高手指点迷津阿,想了一晚上了。

解决方案 »

  1.   

    实在找不到原因才出来问的。
    java东西真多,感觉懂得东西实际上不懂。
    从Spring里结合Hibernate配置BasicDataSource我会。
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
            <property name="url"><value>jdbc:mysql://localhost:3306/</value></property>
            <property name="username"><value>噢噢</value></property>
            <property name="password"><value>33</value></property>
            <property name="maxActive"><value>100</value></property>
            <property name="maxIdle"><value>30</value></property>
            <property name="maxWait"><value>1000</value></property>
        </bean>
    但是我不想用Spring和Hibernate。
    Spring和hibernate很占资源,不好控制。
      

  2.   

    DBCP使用apache的对象池ObjectPool作为连接池的实现,在构造GenericObjectPool时,会生成一个内嵌类Evictor,实现自Runnable接口。如果_timeBetweenEvictionRunsMillis大于0,每过_timeBetweenEvictionRunsMillis毫秒Evictor会调用evict()方法,检查对象的闲置时间是否大于 _minEvictableIdleTimeMillis毫秒(_minEvictableIdleTimeMillis小于等于0时则忽略,默认为30分钟),是则销毁此对象,否则就激活并校验对象,然后调用ensureMinIdle方法检查确保池中对象个数不小于_minIdle。在调用returnObject方法把对象放回对象池,首先检查该对象是否有效,然后调用PoolableObjectFactory 的passivateObject方法使对象处于非活动状态。再检查对象池中对象个数是否小于_maxIdle,是则可以把此对象放回对象池,否则销毁此对象还有几个很重要的属性,_testOnBorrow、_testOnReturn、_testWhileIdle,这些属性的意义是取得、返回对象和空闲时是否进行验证,检查对象是否有效,默认都为false即不验证。所以当使用DBCP时,数据库连接因为某种原因断掉后,再从连接池中取得连接又不进行验证,这时取得的连接实际已经时无效的数据库连接了。网上很多说DBCP的bug应该都是如此吧,只有把这些属性设为true,再提供_validationQuery语句就可以保证数据库连接始终有效了,oracle数据库可以使用SELECT COUNT(*) FROM DUAL,不过DBCP要求_validationQuery语句查询的记录集必须不为空,可能这也可以算一个小小的BUG,其实只要_validationQuery语句执行通过就可以了。
      

  3.   

    兄弟有没有不使用Spring和hibernate来配置c3po的方法?
    因为我的应用里不想用这两个大东西.
    呵呵.
    再问个问题c3po的官方网站是?
    分都给你了.
    感谢支持。那篇文章看过了,我就是纳闷
    每过_timeBetweenEvictionRunsMillis毫秒Evictor会调用evict()方法,检查对象的闲置时间是否大于 _minEvictableIdleTimeMillis毫秒(_minEvictableIdleTimeMillis小于等于0时则忽略,默认为30分钟),是则销毁此对象,
    -------------------------------
    这个问题,我设置了1分钟,minIdle是0,把网站闲置了好久再次访问connection的hashCode还是不变,也就是connection并没有销毁..
    你知道javax.sql.PooledConnection 这个类么?