Application of c3p0 database connection pool and DBUtils tool

Introduction to c3p0 database connection pool

  • In order to solve the database connection problem in traditional development, database connection pool technology can be used
  • The basic idea of ​​the database connection pool is to establish a "buffer pool" for database connections, and put a certain number of connections in the buffer pool in advance. put it back.
  • The database connection pool allocates, manages, and releases database connections. It allows applications to reuse an existing database connection instead of rebuilding a new one.
  • The database connection pool will create a certain number of database connections into the connection pool when it is initialized. The number of these database connections is set by the minimum number of database connections. Regardless of whether these database connections are used, the connection pool will always ensure that at least With such a large number of connections, the maximum number of database connections in the connection pool limits the maximum number of connections that this connection pool can occupy. Whenever the number of connections requested by the application to the connection pool exceeds the maximum number of connections, these requests will be added to the pool. waiting in the queue.

The necessity of JDBC database connection pool

  • When using and developing database-based web programs, the traditional model basically follows these steps:

    ->在主程序(如Servlet、bean)中建立数据库连接
    ->进行sql操作
    ->断开数据库连接
    
  • Problems with this mode of development:

    • Ordinary JDBC database connections are obtained using DriverManager
      . Every time a connection is established to the database, the Connection must be loaded into the memory, and then the user name and password must be verified (it takes 0.05s-1s). When a database connection is required, one is required from the database, and the connection is disconnected after the execution is completed. This method consumes a lot of resources and time. Database connection resources are not well reused. If there are hundreds or even thousands of people online at the same time, frequent database connections will take up a lot of system resources.

    • For each database connection, it must be disconnected after use. Otherwise, if the program fails to close due to an exception, it will cause a memory leak in the database system and eventually cause the database to be restarted.

    • This kind of development cannot control the number of connection objects that are created, and system resources will be allocated without any scruples. If there are too many connections, it may also cause memory leaks and server crashes.

Ready to work

1.> Import the jar package

mchange-commons-java-0.2.3.4.jar
c3p0-0.9.2.1.jar
commons-dbutils-1.7.jar

2.>Create c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <named-config name="helloc3p0">

        <!-- 指定连接数据源的基本属性 -->
        <property name="user">root</property>
        <property name="password">1995</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql:///db_javaee</property>

        <!-- 若服务器中连接数不足时,一次向数据库服务器申请多少个连接 -->
        <property name="acquireIncrement">50</property>
        <!-- 初始化数据库连接池时连接的数量 -->
        <property name="initialPoolSize">5</property>
        <!-- 数据库连接池中的最小的数据库连接数 -->
        <property name="minPoolSize">50</property>
        <!-- 数据库连接池中的最大的数据库连接数 -->
        <property name="maxPoolSize">1000</property>

        <!-- C3P0 数据库连接池可以维护的 Statement 的个数 -->
        <property name="maxStatements">20</property>
        <!-- 每个连接同时可以使用的 Statement 对象的个数 -->
        <property name="maxStatementsPerConnection">5</property> 
    </named-config>
</c3p0-config>

3.> Handwritten JDBCTools.java

package com.anqi.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class JDBCTools {

    private static DataSource dataSource = null;

    //数据库连接池只需要被初始化一次
    static {
        dataSource = new ComboPooledDataSource("helloc3p0");
    }

    public static Connection getConnection() throws Exception {
        return dataSource.getConnection();
    }
    public static void releaseDb(ResultSet resultSet, Statement sta, Connection con) {
        if(resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(sta != null) {
            try {
                sta.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(con != null) {
            try {
                //数据库连接池的 connection 对象进行 close 时
                //并不是真的进行关闭,而是把数据库连接归还到数据库连接池中
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

4.> JUite Test JDBCTools

package com.anqi.jdbc;
import static org.junit.jupiter.api.Assertions.*;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
class JdbcTest {

    @Test
    public void testJDBCTest() throws Exception{
        Connection con = JDBCTools.getConnection();
        System.out.println(con);
    }

    /**
     * 1.创建 c3p0-config.xml 文件,参考帮助文档中 Appenddix B:Configuation B
     * 2.创建 ComboPooledDataSource 实例
     *  DataSource dataSource = new ComboPooledDataSource("helloc3p0");
     * 3.从 DataSource 实例中获取数据库的连接
     * @throws SQLException 
     */
    @Test
    public void testC3p0WithConfig() throws SQLException {
        DataSource dataSource = new ComboPooledDataSource("helloc3p0");
        System.out.println(dataSource.getConnection());
    }

}

5.> Test the DBUTILS tool

package com.anqi.jdbc;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.jupiter.api.Test;


/**
 * 测试 DBUtils 工具类
 */
class DBUtilsTest {

    //1.创建 QueryRunner 对象
    QueryRunner queryRunner = new QueryRunner();


    class MyHandler implements ResultSetHandler{

        public Object handle(ResultSet arg0) throws SQLException {
            //此处对 resultSet 里面的内容进行处理
            return "hahaha";
        }

    }

    /**
     * ScalerHandler:把结果集转为一个数值(可以使任意基本数据类型和字符串、Date等)返回
     */
    @Test
    public void testScalerHandler() {
        Connection con = null;

        try {
            con = JDBCTools.getConnection();
            /*String sql = "SELECT name FROM customers WHERE id=?";*/
            String sql = "SELECT count(id) FROM customers";
            /*Object result = queryRunner.query(con, sql, new ScalarHandler(), 2);*/
            Object result = queryRunner.query(con, sql, new ScalarHandler());
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCTools.releaseDb(null, null, con);
        }       
    }

    /**
     * MapListHandler:将结果集转为一个 Map 的 List
     * Map 对应查询的一条记录:键 -> sql 查询的列名(不是列的别名) 值 -> 列的值
     * 而 MapListHandler:返回的多条记录对应的 Map 集合
     */
    @Test
    public void testMapListHandler() {
        Connection con = null;

        try {
            con = JDBCTools.getConnection();
            String sql = "SELECT * FROM customers WHERE id > ?";
            List<Map<String, Object>> list = queryRunner.query(con, sql, new MapListHandler(), 1);
            System.out.println(list);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCTools.releaseDb(null, null, con);
        }
    }

    /**
     * BeanListHandler:把结果集转为一个 List,该 list 不为 null,但可能
     * 为空集合
     * 而 sql 语的确能够查询到记录,List 中存放创建 BeanListHandler 传入的 class 对应
     * 的对象
     */
    @Test
    public void testBeanListHandler() {
        Connection con = null;

        try {
            con = JDBCTools.getConnection();
            String sql = "SELECT * FROM customers WHERE id > ?";
            List<Customer> list = queryRunner.query(con, sql, new 
            BeanListHandler<>(Customer.class), 1);
            System.out.println(list);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCTools.releaseDb(null, null, con);
        }
    }

    /**
     * BeanHandler:把结果集的第一条记录转为创建 BeanHandler 对象时传入的 class
     * 参数对应的对象
     * 
     */
    @Test
    public void testBeanHandler() {
        Connection con = null;

        try {
            con = JDBCTools.getConnection();
            String sql = "SELECT * FROM customers WHERE id = ?";
            Customer c = queryRunner.query(con, sql, new BeanHandler<>
            (Customer.class), 2);
            System.out.println(c.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCTools.releaseDb(null, null, con);
        }
    }

    /**
     * QueryRunner 的 query 方法的返回值取决于其 ResultSetHandler
     * 的 handle 方法
     */
    @Test
    public void testQuery() {
        Connection connection = null;

        try {
            connection = JDBCTools.getConnection();
            String sql = "SELECT *  FROM customers";
            Object obj =queryRunner.query(connection, sql, new MyHandler());
            System.out.println(obj.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JDBCTools.releaseDb(null, null, connection);
        }
    }

    /**
     * 测试 QueryRunner 的 update 方法
     * 该方法可用于 INSERT ,UPDATE, DELETE
     */
    @Test
    public void testQueryRunnerUpdate() {

        String sql = "DELETE  FROM customers"
                + " WHERE id=?";
        Connection connection = null;

        try {
            connection = JDBCTools.getConnection();
            //2.使用 update 方法
            queryRunner.update(connection, sql, 1);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCTools.releaseDb(null, null, connection);
        }


    }
}

call situation
write picture description here

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325670271&siteId=291194637