数据库连接池的使用(C3P0实现多数据源的数据库连接池)

时间:2022-08-26 14:07:23
    要说数据库连接池,我们先来谈谈对象池的概念。所谓对象池,就是把频繁使用的对象缓存起来,可以重复使用。首先:一个对象的生存周期包括:对象的创建、对象的使用、对象的销毁。
    1、对于对象的创建,我们知道,Java对象是通过构造函数来创建的,在这一过程中,该构造函数链中的所有构造函数也都会被自动调用。另外,默认情况下,调用类的构造函数时,Java会把变量初始化成确定的值:所有的对象被设置成null,整数变量(byte、short、int、long)设置成0,float和double变量设置成0.0,逻辑值设置成false。所以用new关键字来新建一个对象的时间开销是很大的;
    2、对于对象的销毁,Java语言的一个优势,就是Java程序员勿需再像C/C++程序员那样,显式地释放对象,而由称为垃圾收集器(Garbage Collector)的自动内存管理系统,定时或在内存凸现出不足时,自动回收垃圾对象所占的内存。凡事有利总也有弊,这虽然为Java程序设计者提供了极大的方便,但同时它也带来了较大的性能开销。这种开销包括两方面,首先是对象管理开销,GC为了能够正确释放对象,它必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等。其次,在GC开始回收“垃圾”对象时,系统会暂停应用程序的执行,而独自占用CPU。
    3、基于以上的考虑,如果是一个需要频繁被使用的对象(并且该对象在重复使用前,无需任何处理,属于没有状态的对象如String),将极大影响程序的性能,所以引入了对象池技术,核心原理是:缓存和共享即对于那些被频繁使用的对象,在使用完后,不立即将它们释放,而是将它们缓存起来,以供后续的应用程序重复使用,从而减少创建对象和释放对象的次数,进而改善应用程序的性能。事实上,由于对象池技术将对象限制在一定的数量,也有效地减少了应用程序内存上的开销。
   4、 采用对象池化的本意,是要通过减少对象生成的次数,减少花在对象初始化上面的开销,从而提高整体的性能。然而池化处理本身也要付出代价,因此,并非任何情况下都适合采用对象池化。基本上,只在重复生成某种对象的操作成为影响性能的关键因素的时候,才适合进行对象池化。如果进行池化所能带来的性能提高并不重要的话,还是不采用对象池化技术,以保持代码的简明,而使用更好的硬件和更棒的虚拟机来提高性能为佳。
    说了一堆的对象池技术,其实数据连接池在一定程度上采用的技术原理类似对象池技术,我们都知道数据库连接是非常宝贵的资源,而对于数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,采用数据库连接池,它在初始化时创建minConn的数据库连接,允许应用程序复用创建的连接,当连接池有可用连接时,就可以直接从连接池获得而不用频繁向数据库获取连接,大大减轻了数据库的负载。
    以下是我在实际项目中使用C3P0实现的对于多数据库的实现的连接池。


private static Map<String, ComboPooledDataSource> dataSources = new ConcurrentHashMap<String, ComboPooledDataSource>();

private ComboPooledDataSource getDataSource(String connName){
ComboPooledDataSource dataSource = dataSources.get(connName);
        if (dataSource != null) {
            return dataSource;
        }

        

String strConn = String.format("jdbc:%s://%s:%s/%s", dbms, host, port,

db);
if (dbms.equalsIgnoreCase(DBConfig.DatabaseType.SQLServer.toString()))
strConn = String.format("jdbc:sqlserver://%s:%s;DatabaseName=%s",
host, port, db);


        String dbUrl = strConn;
        String dbUser = user;
        String dbPwd = password;

        String driver = dbmsDriver;

        dataSource = new ComboPooledDataSource();
        dataSource.setUser(dbUser);
        dataSource.setPassword(dbPwd);
        dataSource.setJdbcUrl(dbUrl);
        try {
dataSource.setDriverClass(driver);
} catch (PropertyVetoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

        dataSource.setInitialPoolSize(10);
        dataSource.setMinPoolSize(10);
        dataSource.setMaxPoolSize(100);
        dataSource.setMaxStatements(100);
        dataSource.setMaxIdleTime(60);
        dataSource.setAcquireIncrement(10);
        dataSources.put(connName, dataSource);

        return dataSource;
    }
//**************************连接池的使用**************************//