Java——数据库编程JDBC之数据库连接池技术(C3P0与Druid,提供了Druid的工具类)

时间:2022-07-25
本文章向大家介绍Java——数据库编程JDBC之数据库连接池技术(C3P0与Druid,提供了Druid的工具类),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

上篇博文中讲解的JDBC,程序中每次都要获取数据库连接,使用完毕后直接释放资源,实际上这种在实际应用中是不可取的,因为效率很低,所以,本文来总结下数据库连接池技术。

1 数据库连接池概念

数据库连接池就是一个存放数据库连接的容器(集合),当系统初始化后容器被创建,容器会申请一些连接对象,当用户访问数据库时,从容器中获取连接对象,用户访问完后会将连接对象归还给容器。使用连接池的好处

  • 节约资源;
  • 用户访问高效。

2 数据库连接池的实现

在javax.sql包下有一个标准接口DataSource,两个方法:

  • 获取连接:getConnection();
  • 归还连接:Connection.close(),若连接对象是从连接池中获取的,那么调用方法时不会再关闭连接,而是归还连接。

一般不需要用户实现,由数据库厂商实现。本文讲解两种不同的数据库连接池技术实现:

  • C3P0:数据库连接池技术(较老);
  • Druid:数据库连接池技术,性能较高,应用较广泛,由阿里巴巴提供的。

3 C3P0数据库连接池技术

3.1 使用步骤

  • 1)导入两个jar包:c3p0-0.9.5.2.jar、mchange-commons-java-0.2.12.jar(注意:另外别忘了数据库的驱动jar包);
  • 2)定义配置文件,名称必须为c3p0.properties 或者 c3p0-config.xml,文件直接放在src目录下;
  • 3)创建数据库连接池对象ComboPooledDataSource;
  • 4)获取连接:getConnection()。

【举例】:基本使用案例如下:

3.2 配置文件

c3p0-config.xml配置文件中包含了default-config默认的配置和named-config name="otherc3p0"自定义的配置,在创建数据库连接对象时,没有参数时使用默认的配置,有参数时使用指定的配置。

【配置文件c3p0-config.xml】:源码见下,有具体注释,不再赘述

<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>
  	<!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db1</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 连接池参数 -->
    <!-- 初始化申请的连接数量   -->
    <property name="initialPoolSize">5</property>
    <!-- 最大的连接数量,超过这个数量后会报错   -->
    <property name="maxPoolSize">10</property>
    <!-- 超时时间   -->
    <property name="checkoutTimeout">3000</property>
  </default-config>

  <named-config name="otherc3p0"> 
    <!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/db1</property>
    <property name="user">root</property>
    <property name="password">root</property>
    
    <!-- 连接池参数 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">8</property>
    <property name="checkoutTimeout">1000</property>
  </named-config>
</c3p0-config>

如下的demo演示了获取最大连接数量及归还连接的操作:

public class C3p0Demo1 {
    public static void main(String[] args) throws SQLException {
        //1、创建数据库连接对象,使用默认配置
        // 使用指定名称的配置
//        DataSource ds = new ComboPooledDataSource("otherc3p0");
        DataSource ds = new ComboPooledDataSource();
        //2、获取连接对象
        for (int i = 0; i < 11; i++) {  //演示获取最大连接数量
            Connection conn = ds.getConnection();
            System.out.println(i+":"+conn);
            if(i == 5){
                conn.close(); //归还连接
            }
        }
    }
}

4 Druid数据库连接池技术

PS:由阿里巴巴提供,应用非常广泛,我们实际做项目时推荐使用。

4.1 使用步骤

  • 1)导入jar包:druid-1.0.9.jar(注意:另外别忘了数据库的驱动jar包);
  • 2)定义配置文件:properties文件形式,可以定义为任意名称,可放在任意目录下,需要手动加载至工程中;
  • 3)加载配置文件:Properties;
  • 4)获取数据库连接池对象:通过工厂类DruidDataSourceFactory.createDataSource()获取;
  • 5)获取连接:getConnection()。

【举例】:基本使用案例如下

public class DruidDemo1 {
    public static void main(String[] args) throws Exception {
        //1、导入jar包
        //2、定义配置文件
        //3、加载配置文件
        Properties pro = new Properties();
        InputStream is = DruidDemo1.class.getClassLoader().getResourceAsStream("druid.properties");
        pro.load(is);
        //4、获取连接池对象
        DataSource ds = DruidDataSourceFactory.createDataSource(pro);
        //5、获取连接
        Connection connection = ds.getConnection();
        System.out.println(connection);
    }
}

4.2 Druid工具类

我们使用Druid数据库连接池技术,为了方便使用,可以对其常用的操作进行封装,形成一个工具JdbcUtils工具类:

1)要有静态代码块,加载配置文件,初始化连接池对象;

2)提供几种方法:

  • 获取连接方法:通过数据库连接池获取;
  • 释放资源;
  • 获取连接池的方法;

【Druid 的工具类】:

//Druid数据库连接池的工具类
public class JdbcUtils {

    //1、定义成员变量DataSource
    private static DataSource ds;

    static {
        try {
            // 1、加载配置文件
            Properties pro = new Properties();
            pro.load(JdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
            //2、获取DataSource
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取连接
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }

    //释放资源
    public static void close(Statement stmt,Connection conn){
        close(stmt,conn,null);
    }

    public static void close(Statement stmt, Connection conn, ResultSet rs){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(stmt!=null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close(); //归还连接
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //获取连接池
    public static DataSource getDataSource(){
        return ds;
    }
}

【举例】:使用JdbcUtils工具类插入一条数据

public class DruidDemo2 {
    public static void main(String[] args) {
        //完成添加操作,在db1 的account表中添加一条记录
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            //1、获取连接
            conn = JdbcUtils.getConnection();
            //2、定义sql
            String sql = "insert into account values(null,?,?)";
            //3、获取pstmt对象
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1,"wangwu");
            pstmt.setDouble(2,100);
            int cnt = pstmt.executeUpdate();
            System.out.println(cnt);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtils.close(pstmt,conn);
        }
    }
}

———————————————————————————————————————

本文为博主原创文章,转载请注明出处!