Java Web(day12) —— 数据库连接池与DBUtils工具

一、数据库连接池

1、数据库连接池的概念

   用池来管理Connection,这可以重复使用Connection。有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。池就可以再利用这个Connection对象了。

Java Web(day12) —— 数据库连接池与DBUtils工具

2.DataSource接口

JDBC提供了javax.sql.DataSource接口,它负责建立与数据库的连接,在应用程序中访问数据库时不必编写连接数据库的代码,可以直接从数据源获得数据库连接

(1)数据库和连接池

在DataSource中事先建立了多个数据库连接,这些数据库连接保存在连接池(ConnectPool)中。java程序访问数据库时,只需要从连接池中取出空闲状态的数据库连接,当程序访问数据库结束,再将数据库连接放回连接池,这样做可以调高访问数据库的效率。

如果Web应用每次接收到客户的请求,都和数控建立一个连接,数控操作结束就断开连接,这样会消费大量的时间和资源。因为数据库每次配置连接都要将Connection对象加载到内存中,再验证用户名和密码。

(2)数据源和JNDI资源

由于DataSource对象是由Tomcat提供的,因此不能够在程序中创建一个DataSource对象,而要采用JNDI技术来获得DataSource对象的引用。
   可以简单的把JNDI理解为一种将对象和名字绑定的技术,对象工厂负责生产出对象,这些对象都和唯一的名字绑定,外部程序可以通过名字来获得某个对象的引用。在javax.naming包中提供了Context接口,该接口提供了将对象和名字绑定,以及通过名字检索对象的方法。

Java Web(day12) —— 数据库连接池与DBUtils工具
3.DBCP数据源

DBCP是Apache提供的一款开源免费的数据库连接池!Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。Hibernate3.0之后不再对DBCP提供支持!因为Hibernate声明DBCP有致命的缺欠!

需要应用程序应在系统中增加如下两个 jar 文件:

·Commons-dbcp.jar:连接池的实现
·Commons-pool.jar:连接池实现的依赖库

实现DBCP

(1)加入jar包

(2)编写dbcpconfig.properties

#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/testdb
username=root
password=123456

#<!-- 初始化连接 -->
initialSize=10

#最大连接数量
maxActive=50

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

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

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


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

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

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

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

(3)在获取数据库连接的工具类(如jdbcUtils)的静态代码块中创建池

package cn.zy.utils;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;


/*
 * 数据库连接工具类DBCP
 */
public class JdbcUtils_DBCP {
    /*
     * 在java中,编写数据库连接池需实现java.sql.DataSource接口,每一种数据库连接池都是DataSource接口的实现
     * DBCP连接池就是javax.sql.DataSource接口的一个具体实现
     */
    private static DataSource ds =null;
    //在静态代码块中创建数据库连接池
    static {
        try {
            //加载配置文件
            InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
            Properties prop = new Properties();
            prop.load(in);
            //创建数据源
             ds = BasicDataSourceFactory.createDataSource(prop);
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }
    
    /*
     * 从数据源中获取数据库连接
     */
    public static Connection getConnection() throws SQLException{
        return ds.getConnection();
    }
    
    /*
     * 释放资源
     */
    public static void release(Connection conn,Statement st,ResultSet rs){
        if(rs!=null){
            try{
                rs.close();
            }catch (Exception e){
                e.printStackTrace();
            }
            if(st!=null){
                try {
                    st.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if(conn!=null){
                    try {
                        conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

测试连接

package cn.zy.test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.junit.Test;

import cn.zy.utils.JdbcUtils_DBCP;

/*
 * 测试DBCP数据源
 */
public class DbcpTest {
    @Test
    public void dbcpDataSourceTest(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            //获取数据库连接
            conn = JdbcUtils_DBCP.getConnection();
            String sql = "insert into account(name,money) values(?,?)";
            st = conn.prepareStatement(sql);
            st.setString(1, "D");
            st.setFloat(2, 2000);
            st.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
             //释放资源
           JdbcUtils_DBCP.release(conn, st, rs);
        }
    }

}

4.C3P0数据源

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。C3P0数据源在项目开发中使用得比较多。

c3p0与dbcp区别:

·dbcp没有自动回收空闲连接的功能
·c3p0有自动回收空闲连接功能

在应用程序中加入C3P0连接池

(1)导入相关jar包

c3p0-0.9.2-pre1.jar、mchange-commons-0.2.jar,如果操作的是Oracle数据库,那么还需要导入c3p0-oracle-thin-extras-0.9.2-pre1.jar

(2)在src下加入C3P0的配置文件:c3p0-config.xml,注意:

配置文件要求:

l 文件名称:必须叫c3p0-config.xml

l 文件位置:必须在src下

c3p0-config.xml的配置信息如下:

<?xml version="1.0" encoding="UTF-8"?>
<!--
c3p0-config.xml必须位于类路径下面
private static ComboPooledDataSource ds;
static{
    try {
        ds = new ComboPooledDataSource("MySQL");
    } catch (Exception e) {
        throw new ExceptionInInitializerError(e);
    }
}
-->

<c3p0-config>
    <!--
    C3P0的缺省(默认)配置,
    如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源
    -->
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/testdb</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        
        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </default-config>

    <!--
    C3P0的命名配置,
    如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”这样写就表示使用的是name是MySQL的配置信息来创建数据源
    -->
    <named-config name="MySQL">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/testdb</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        
        <property name="acquireIncrement">5</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">5</property>
        <property name="maxPoolSize">20</property>
    </named-config>

</c3p0-config>

(3)在获取数据库连接的工具类(如jdbcUtils)的静态代码块中创建池

package cn.zy.utils;

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 JdbcUtils_C3P0 {
    private static ComboPooledDataSource dataSource = null;
    //在静态块中创建数据库连接池
    static{
        try {
            //通过代码创建数据库连接池
            /*ds = new ComboPooledDataSource();
            ds.setDriverClass("com.mysql.jdbc.Driver");
            ds.setJdbcUrl("jdbc:mysql://localhost:3306/testdb");
            ds.setUser("root");
            ds.setPassword("123456");
            ds.setInitialPoolSize(10);
            ds.setMinPoolSize(5);
            ds.setMinPoolSize(20);*/

            //通过读取xml来获取数据源
            //ds = new ComboPooledDataSource();//使用C3P0的默认配置来创建数据源
            dataSource = new ComboPooledDataSource("MySQL");//使用C3P0的命名配置来创建数据源
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    /*
     * 从数据源中获取数据库连接
     */
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    /*
     * 返回连接池
     */
    public static DataSource getDataSource() {
        return dataSource;
    }
    /*
     * 释放资源
     */
    public static void release(Connection conn,Statement st,ResultSet rs){
        if(rs!=null){
            try{
                //关闭存储查询结果的ResultSet对象
                rs.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
            rs = null;
        }
        if(st!=null){
            try{
                //关闭负责执行SQL命令的Statement对象
                st.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }

        if(conn!=null){
            try{
                //将Connection连接对象还给数据库连接池
                conn.close();
            }catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

编写测试类:

package cn.zy.test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.junit.Test;

import cn.zy.utils.JdbcUtils_C3P0;

public class C3p0Test {
    @Test
    public void fun(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils_C3P0.getConnection();
            String sql = "insert into account(name,money) values(?,?)";
            st = conn.prepareStatement(sql);
            st.setString(1, "F");
            st.setFloat(2,3000);
            st.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

二、DBUtils工具

1.DBUtils工具介绍

DButils是JDBC的简化开发工具包。需要导入commons-dbutils-1.6.jar才能够正常使用DButils工具类

DButils封装了对JDBC的操作,简化了JDBC操作,可以少些代码。DButils的三个核心功能:

·QueryRunner提供了对sql语句操作的API

·ResultSetHandler接口,用于定义select操作后怎样去封装结果

· DButils类,是一个工具类,定义了关闭资源与事物处理的方法

2.QueryRunner类

(1)query(Connection conn,String sql,ResultSetHandler rsh,Object…params),用来完成表数据的查询操作。
esultSetHandler结果集处理类
Java Web(day12) —— 数据库连接池与DBUtils工具

(2)update(Connection conn,String sql,Object…params),用于完成表数据增加、删除、修改的操作

3、ResultSetHandler接口

该接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形式。
ResultSetHandler接口提供了一个单独的方法:Object handle(java.sql.ResultSet.rs)。

4.ResultSetHandler实现类

ArrayHandler:把结果集中的第一行数据转换成对象数组。

ArrayListHandler:把结果集中的每一行数据都转换成一个对象数组,再存放到List中。

BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。

BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。

MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。

MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List。

ColumnListHandler:将结果集中某一列的数据存放到List中。

KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里(List),再把这些map再存到一个map里,其key为指定的列。

ScalarHandler:获取结果集中第一行数据指定列的值,常用来进行单值查询
上一篇:DAY12 补vue中引入cesium并初始化样式


下一篇:Verilog 刷题笔记(05)