数据库连接的建立及关闭是一种极耗系统资源的操作,尤其是在多层结构的应用环境中,这种资源的耗费对系统性能影响尤为明显。在工作时做系统优化对这方面的很有体会,相同功能的查询语句,由于打开关闭数据库连接的次数不同导致两个查询语句耗费的时间差别很大。一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完后立即关闭连接。频繁地打开、关闭连接将会造成系统性能低下。虽然写高性能的sql语句能够减少访问数据库的次数,但是也不能完全规避平凡操作数据库的的行为,因为有时候我们访问量大,就会伴有多线程和高并发,这时候我们就该考虑还有什么办法能提高系统的性能了。办法总比问题多,数据库连接池的使用帮我们大大的降低了平凡的开关数据库。
数据库连接池的解决方案是:当应用程序启动时,系统主动建立足够的数据库连接,并将这些连接组成一个连接池。每次应用程序请求数据库连接时,无须重新打开连接,而是从池中取出已有的连接使用,使用完后,虽然使用了close()关闭连接,但是没有真正关闭数据库连接,而是直接将连接归还给了连接池。通过使用连接池,将大大提高程序运行效率。
1、数据库连接池是Connection对象的工厂。数据库连接池的常用参数有如下:
● 数据库的初始连接数
● 连接池的最大连接数
● 连接池的最小连接数
● 连接池的每次增加的容量
... ...
2、JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由商用服务器(如webLogic、WebSphere)等提供实现,也有一些开源组织提供实现(如DBCP和 C3P0等)。商用的我就不多介绍了,一般都是根据提示配置一下就可以使用了。下面简单的说一下上面这两个开源的常用配置属性,真用到了还可以参考文档进行详细的配置。
3、DBCP(DataBaseconnection pool),数据库连接池。是apache上的一个java连接池,也是tomcat使用的连接池组件。单独使用dbcp需要3个包:common-dbcp.jar,common-pool.jar,common-collections.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。下面是一些常用的设置属性
//创建数据源对象 BasicDataSource ds = new BasicDataSource(); //设置连接池所需的驱动(以MySql为例) ds.SetDriverClassName("com.mysql.jdbc.Driver"); //设置连接数据库的url ds.setUrl("jdbc:mysql://localhost:3306/javaee"); //设置连接数据库的用户名 ds.setUsername("root"); //连接数据库的密码 ds.setPassword("root"); //设置连接池的初始连接数 ds.setInitia1Size(5); //设置连接池最多可有有多少个活动连接数 ds.setMaxActive(10); //设置连接池中最少有2个空闲的连接 ds.setMinIdle(2); //通过数据源获取连接 Connection conn = ds.getConnection(); //释放数据库连接 Conn.close(); |
数据源和数据库连接不同,数据源无须创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。建议把上面程序中的ds设置成static成员变最,并且在应用开始时立即初始化数据源对象,程序中所有需要获取数据库连接的地方直接访问该ds对象,并获取数据库连接即可,当数据库访问结束后,程序还是像以前一样关闭数据库连接即可。
4、C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。C3P0不仅可以自动清理不在使用的Connection,还可以自动清理Statement和ResultSet。目前使用它的开源框架有Hibernate,Spring等。
//创建连接池对象 ComboPooledDataSource ds = new ComboPooledDataSource(); //设置连接池所需的驱动(以MySql为例) ds.SetDriverClass("com.mysql.jdbc.Driver"); //设置连接数据库的url ds.setJdbcUrl("jdbc:mysql://localhost:3306/javaee"); //设置连接数据库的用户名 ds.setUser("root"); //连接数据库的密码 ds.setPassword("root"); //设置连接池的最大连接数 ds.setMaxPoolSize(20); //设置连接池中最少连接数 ds.setMinPoolSize(2); //设置连接池的初始连接数 ds.setInitia1PoolSize(5); //设置连接池的缓存Statement的最大数 ds.setMaxStatements(100); //获取连接 Connection conn = ds.getConnection(); //释放数据库连接 Conn.close(); |
看到了数据库连接池的使用,我们是不是很快就会想到多线程编程里是不是也有线程池帮我们解决一些性能问题呢?答案肯定的,想到了就去尝试吧......