• JDBC 连接池的两种方式——dbcp & c3p0


    申明:本文对于连接资源关闭采用自定义的 JDBCUtils 工具:

    package com.test.utils;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    public final class JDBCUtils {
        private static String driver="com.mysql.jdbc.Driver";
        private static String url="jdbc:mysql://localhost:3306/store28";
        private static String user="root";
        private static String password="root1234";
        
        private JDBCUtils(){}
        
        static {
            /**
             * 驱动注册
             */
            try {
                Class.forName(driver);
            } catch (ClassNotFoundException e) {
                throw new ExceptionInInitializerError(e);
            }
            
        }
        
        /**
         * 获取 Connetion
         * @return
         * @throws SQLException
         */
        public static Connection getConnection() throws SQLException{
            return DriverManager.getConnection(url, user, password);
        }
        
        /**
         * 释放资源
         * @param conn
         * @param st
         * @param rs
         */
        public static void colseResource(Connection conn,Statement st,ResultSet rs) {
            closeResultSet(rs);
            closeStatement(st);
            closeConnection(conn);
        }
        
        /**
         * 释放连接 Connection
         * @param conn
         */
        public static void closeConnection(Connection conn) {
            if(conn !=null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            //等待垃圾回收
            conn = null;
        }
        
        /**
         * 释放语句执行者 Statement
         * @param st
         */
        public static void closeStatement(Statement st) {
            if(st !=null) {
                try {
                    st.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            //等待垃圾回收
            st = null;
        }
        
        /**
         * 释放结果集 ResultSet
         * @param rs
         */
        public static void closeResultSet(ResultSet rs) {
            if(rs !=null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            //等待垃圾回收
            rs = null;
        }
    }

    一、连接池技术基本原理

      在程序初始化的时候创建一个 Connection 集合,便于快速增删,可以使用 LinkedList 集合来存储,

      当调用工具者获取一个 Connection 时,就从集合里移除一个 Connection 返回给调用者(期间,如果没有则创建一个连接池)

      当使用完 Connection 之后,使用 close() (Connection的 close() 方法) 将 Connection 资源归还(添加回)List 集合中,但是其中有一个问题,原始的 Connection 中的 close() 方法将资源关闭,因此需要想办法解决这个问题,可以使用如下技术:

      装饰者设计模式、适配器设计模式、基于接口的动态代理、基于子类的动态代理。 

    二、使用 DBCP 技术实现连接池

      使用 properties 配置文件进行数据库连接配置(使用 eclipse 将 dbcp.properties 文件编写在 src 目录下):

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/store28
    username=root
    password=root1234

    说明:以下是全配置信息

    #连接基本设置
    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/sys
    username=root
    password=root1234


    #<!--扩展配置 了解-->
    #初始化连接
    initialSize=10

    #最大连接数量
    maxActive=50

    #<!-- 最大空闲连接 -->
    maxIdle=20

    #<!-- 最小空闲连接 -->
    minIdle=5

    #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
    maxWait=60000

    #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
    #注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
    connectionProperties=useUnicode=true;characterEncoding=gbk

    #指定由连接池所创建的连接的自动提交(auto-commit)状态。
    defaultAutoCommit=true

    #driver default 指定由连接池所创建的连接的只读(read-only)状态。
    #如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
    defaultReadOnly=

    #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
    #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
    defaultTransactionIsolation=READ_UNCOMMITTED

    编写 DBCPUtils 工具类:

    package com.test.utils;
    
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.util.Properties;
    
    import javax.sql.DataSource;
    
    import org.apache.commons.dbcp.BasicDataSourceFactory;
    
    public class DBCPUtils {
        private static DataSource dataSource;
        
        static {
            try {
                InputStream is = DBCPUtils.class.getClassLoader().getResourceAsStream("dbcp.properties");
                Properties props = new Properties();
                props.load(is);
                dataSource = BasicDataSourceFactory.createDataSource(props);
            } catch (Exception e) {
                throw new ExceptionInInitializerError("数据源初始化失败!");
            }
        }
        
        public static Connection getConnection() {
            try {
                return dataSource.getConnection();
            } catch (SQLException e) {
                throw new RuntimeException("数据连接获取失败!");
            }
        }
        
        public static DataSource getDataSource() {
            return dataSource;
        }
    }

    测试:

    package com.test.jdbcTest;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.junit.Test;
    
    import com.test.utils.DBCPUtils;
    import com.test.utils.JDBCUtils;
    
    public class DBCPDmeo {
        @Test
        public void test1() throws SQLException {
            Connection conn = DBCPUtils.getConnection();
            
            String sql = "select cid,cname from category";
            PreparedStatement st = conn.prepareStatement(sql);
            
            ResultSet rs = st.executeQuery();
    
            while(rs.next()) {
                System.out.println(rs.getString("cid")+"..."+rs.getString("cname"));
            }
            JDBCUtils.colseResource(conn, st, rs);
        }
        
        
    }

     三、使用 C3P0 技术实现连接池

     首先配置 c3p0-config.xml 文件(详见 c3p0 官网)

    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
    <default-config>
    <property name="automaticTestTable">con_test</property>

    <!-- 连接数据库配置信息 -->

    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/store28</property>
    <property name="user">root</property>
    <property name="password">root1234</property>

    <property name="checkoutTimeout">30000</property>
    <property name="idleConnectionTestPeriod">30</property>
    <property name="initialPoolSize">10</property>
    <property name="maxIdleTime">30</property>
    <property name="maxPoolSize">100</property>
    <property name="minPoolSize">10</property>
    <property name="maxStatements">200</property>

    <user-overrides user="test-user">
    <property name="maxPoolSize">10</property>
    <property name="minPoolSize">1</property>
    <property name="maxStatements">0</property>
    </user-overrides>

    </default-config>

    <!-- This app is massive! -->
    <named-config name="intergalactoApp">
    <property name="acquireIncrement">50</property>
    <property name="initialPoolSize">100</property>
    <property name="minPoolSize">50</property>
    <property name="maxPoolSize">1000</property>

    <!-- intergalactoApp adopts a different approach to configuring statement
    caching -->
    <property name="maxStatements">0</property>
    <property name="maxStatementsPerConnection">5</property>

    <!-- he's important, but there's only one of him -->
    <user-overrides user="master-of-the-universe">
    <property name="acquireIncrement">1</property>
    <property name="initialPoolSize">1</property>
    <property name="minPoolSize">1</property>
    <property name="maxPoolSize">5</property>
    <property name="maxStatementsPerConnection">50</property>
    </user-overrides>
    </named-config>
    </c3p0-config>

    C3P0Utils 工具:

    package com.test.utils;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import javax.sql.DataSource;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class C3P0Utils {
        private static ComboPooledDataSource dataSource  = new ComboPooledDataSource();
        
        public static Connection getConnection() {
            try {
                return dataSource.getConnection();
            } catch (SQLException e) {
                throw new RuntimeException("数据连接获取失败!");
            }
        }
        
        public static DataSource getDataSource() {
            return dataSource;
        }
    }

    测试:

    package com.test.jdbcTest;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    import org.junit.Test;
    
    import com.test.utils.C3P0Utils;
    import com.test.utils.JDBCUtils;
    
    public class C3p0Test {
        @Test
        public void test() throws SQLException {
            Connection conn = C3P0Utils.getConnection();
            
            String sql = "select cid,cname from category";
            PreparedStatement st = conn.prepareStatement(sql);
            
            ResultSet rs = st.executeQuery();
    
            while(rs.next()) {
                System.out.println(rs.getString("cid")+"..."+rs.getString("cname"));
            }
            JDBCUtils.colseResource(conn, st, rs);
        }
    }
  • 相关阅读:
    django rest framework serializers解读
    django rest framework通用view
    scrapy爬取伯乐在线文章
    scrapy 框架入门
    django rest framework mixins小结
    python 函数进阶
    python 变量进阶(理解)
    Docker 部署Django项目
    Docker部署Vue 工程包
    saltstack 初始化LINUX系统
  • 原文地址:https://www.cnblogs.com/mujingyu/p/7882036.html
Copyright © 2020-2023  润新知