• 第十八章《JDBC》第4节:数据库连接池


    数据库连接的建立及关闭是极耗费系统资源的操作,在多层结构的应用环境中,这种资源的耗费对系统性能影响尤为明显。通过DriverManager获得的数据库连接,一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完后立即关闭连接。频繁地打开、关闭连接将造成系统性能低下。

    数据库连接池的解决方案是:当应用程序启动时,系统主动建立足够的数据库连接,并将这些连接组成一个连接池。每次应用程序请求数据库连接时,无须重新打开连接,而是从连接池中取出已有的连接使用,使用完后不再关闭数据库连接,而是直接将连接归还给连接池。通过使用连接池,将大大提高程序的运行效率。

    对于共享资源的情况,有一个通用的设计模式:资源池(Resource Pool),这种设计模式用于解决资源的频繁请求、释放所造成的性能下降。为了解决数据库连接的频繁请求、释放,JDBC 2.0规范引入了数据库连接池技术。数据库连接池是Connection对象的工厂。数据库连接池的常用参数有:数据库的初始连接数、连接池的最大连接数、连接池的最小连接数、连接池每次增加的容量等。

    JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由商用服务器如WebLogic、WebSphere等提供实现,也有一些开源组织提供实现,如DBCP和C3P0等,这些开源组织提供的实现可供开发者免费使用,本小节将讲解DBCP和C3P0的使用。

    18.4.1 DBCP数据源

    DBCP是Apache软件基金组织下的开源连接池实现,该连接池依赖该组织下的另一个开源系统common-pool。如果需要使用该连接池实现,则应在项目中增加相应的两个jar文件,到本书成书时,这两个jar文件的最新版本名称为:commons-dbcp2-2.9.0.jar和commons-pool2-2.6.2.jar。读者登录http://comons.apache.org即可下载commons-dbcp2-2.9.0-bin.zip和commons-pool2-2.6.2-bin.zip两个压缩文件,解压缩这两个文件即可得到上面提到的两个JAR文件,此外还要额外加入一个commons-logging-1.1.1.jar文件,本书的代码文件夹中会直接对读者提供这三个jar文件。

    为了在程序中使用这两个JAR文件,应该把它们添加到CLASSPATH中。把jar文件添加到CLASSPATH中的操作在本章第18.2.2小节已经做过讲解,此处不再赘述。下面的【例18_09】展示了使用DBCP数据源在程序中的使用。

    【例18_09 DBCP数据源】

    Exam18_09.java

    1. import org.apache.commons.dbcp2.BasicDataSource;
    2. import java.sql.*;
    3. import javax.sql.*;
    4. public class Exam18_09 {
    5. public static void main(String[] args) {
    6. Connection con = null;
    7. Statement stm = null;
    8. ResultSet rs = null;
    9. //创建数据源对象
    10. BasicDataSource ds = new BasicDataSource() ;
    11. //设置连接池所需的驱动
    12. ds.setDriverClassName (Util1.driverName) ;
    13. //设置连接数据库的URL
    14. ds. setUrl (Util1.url) ;
    15. //设置连接数据库的用户名
    16. ds . setUsername (Util1.user) ;
    17. //设置连接数据库的密码
    18. ds. setPassword(Util1.password) ;
    19. //设置连接池的初始连接数
    20. ds .setInitialSize(5) ;
    21. //设置最大连接数
    22. ds.setMaxTotal(20);
    23. //设置连接池中最少有2个空闲的连接
    24. ds. setMinIdle (2);
    25. try {
    26. con = ds.getConnection();
    27. stm = con.createStatement();
    28. String sql = "select * from users";
    29. rs = stm.executeQuery(sql);
    30. System.out.printf("%-10s%-10s%-12s%-15s%-18s\n","玩家QQ号","玩家昵称","玩家性别","玩家生日","玩家手机号");
    31. while (rs.next()) {
    32. String userQQ = rs.getString("user_qq");
    33. String userName = rs.getString("user_name");
    34. String userSex = rs.getString("user_sex");
    35. String userBirthday = rs.getString("user_birthday");
    36. String userPhone = rs.getString("user_phone");
    37. System.out.printf("%-15s%-15s%-15s%-18s%-18s\n",userQQ,userName,userSex,userBirthday,userPhone);
    38. }
    39. }catch (SQLException e){
    40. e.printStackTrace();
    41. }finally {
    42. try {
    43. Util1.close(rs,stm,con);//①关闭rs和stm并释放con
    44. }catch (SQLException e){
    45. e.printStackTrace();
    46. }
    47. }
    48. }
    49. }

    本例代码中配置数据源的各项参数值(驱动类名称、用户名、密码等)都来源于Util1类的静态属性,实际上这些参数也可以被写到配置文件中,在使用时从文件中读出各项参数值。

    数据源和数据库连接不同,数据源无须创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可,也就是说,对于一个应用,创建并设置数据源的代码只要写一次即可。一般会把建议把上面程序中的ds设置成static成员变量,并用静态块对其进行初始化,程序中所有需要获取数据库连接的地方直接访问该ds对象,并获取数据库连接即可。此外,程序中的语句①调用了Util1类的静态方法close(),这个方法中有执行了con.close(),需要说明,数据源所产生的Connection对象与用DriverManager获得的Connection对象不同,数据源所产生的Connection对象执行close()方法只是把对象归还给连接池以便再次使用它,并没有真正关闭Connection对象。【例18_09】的执行结果与【例18_01】完全相同。

    18.4.2 C3P0数据源

    相比DBCP,C3P0数据源性能更胜一筹。C3P0 连接池不仅可以自动清理不再使用的Connection,还可以自动清理Statement和ResultSet。如果需要使用C3P0连接池,则应在系统中增加相应的jar文件,目前为止最新版本的jar文件名称是c3p0-0.9.5.5.jar,读者登录htp://ourceforge.net/prjects/c3p0/站点即可下载C3P0数据源的最新版本jar文件,本书的代码文件夹也直接为读者提供该文件。下面的【例18_10】展示了如何使用C3P0数据源建立连接并完成相应的操作。

    【例18_10 C3P0数据源】

    Exam18_10.java

    1. import com.mchange.v2.c3p0.ComboPooledDataSource;
    2. import java.sql.*;
    3. import javax.sql.*;
    4. public class Exam18_10 {
    5. public static void main(String[] args) {
    6. Connection con = null;
    7. Statement stm = null;
    8. ResultSet rs = null;
    9. try {
    10. //创建数据源对象
    11. ComboPooledDataSource ds = new ComboPooledDataSource() ;
    12. //设置连接池连接数据库所需的驱动
    13. ds.setDriverClass (Util1.driverName) ;
    14. //设置连接数据库的URL
    15. ds.setJdbcUrl (Util1.url) ;
    16. //设置连接数据库的用户名
    17. ds.setUser (Util1.user) ;
    18. //设置连接数据库的密码
    19. ds.setPassword(Util1.password) ;
    20. //设置连接池的最大连接数
    21. ds.setMaxPoolSize(40) ;
    22. //设置连接池的最小连接数
    23. ds.setMinPoolSize(2) ;
    24. //设置连接池的初始连接数
    25. ds.setInitialPoolSize(10) ;
    26. //设置连接池的缓存Statement的最大数
    27. ds. setMaxStatements (180) ;
    28. con = ds.getConnection();
    29. stm = con.createStatement();
    30. String sql = "select * from users";
    31. rs = stm.executeQuery(sql);
    32. System.out.printf("%-10s%-10s%-12s%-15s%-18s\n","玩家QQ号","玩家昵称","玩家性别","玩家生日","玩家手机号");
    33. while (rs.next()) {
    34. String userQQ = rs.getString("user_qq");
    35. String userName = rs.getString("user_name");
    36. String userSex = rs.getString("user_sex");
    37. String userBirthday = rs.getString("user_birthday");
    38. String userPhone = rs.getString("user_phone");
    39. System.out.printf("%-15s%-15s%-15s%-18s%-18s\n",userQQ,userName,userSex,userBirthday,userPhone);
    40. }
    41. }catch (Exception e){
    42. e.printStackTrace();
    43. }
    44. }
    45. }

    在【例18_10】的代码中,rs、stm、con都无需执行关闭操作,这是因为C3P0数据源能够自动自动释放它们。【例18_10】的运行结果也与【例18_01】相同。

    除阅读文章外,各位小伙伴还可以点击这里观看我在本站的视频课程学习Java!

  • 相关阅读:
    C语言——初识函数
    pytest + yaml 框架 -55. raw 不转义模板语法
    深度优先搜索&广度优先搜索
    登录提示 ORA-28000 The account is locked.
    【Flutter】Android Studio的Flutter环境配置
    分享一下 iOS 发布/测试证书 申请过程
    Docker镜像制作及使用Dockerfile制作镜像
    算法导论第16章 贪心算法之活动选择
    华为机试真题 C++ 实现【打印机队列】【2022.11 Q4 新题】
    数据库的基本概念
  • 原文地址:https://blog.csdn.net/shalimu/article/details/128134992