【Java】连接池与DBUtils的使用

目录

1.为什么要使用连接池

2.自定义连接池-初级版本

3.自定义连接池-进阶版本

4.装饰者模式

5.自定义连接池-终极版本

6.C3P0连接池

1.通过硬编码来编写【了解】

2.通过配置文件来编写

3.使用c3p0改写工具类

7.DRUID连接池

1.通过硬编码方式【了解】

2.通过配置文件方式

3.Druid工具类的制作

8.DBUtils完成增删改

9.DBUtils完成查询

查询一条记录(使用ArrayHandler,使用BeanHandler,使用MapHandler)

查询多条数据封装到List集合中(使用ArrayListHandler,使用BeanListHandler,使用MapListHandler)

查询单个数据(使用ScalarHandler())

查询单列多个值(使用ColumnListHandler)

10.元数据

参数元数据

结果集元素数据

11.自定义DBUtils增删改


1.为什么要使用连接池

Connection对象在JDBC使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了(close).每次创建和销毁对象都是耗时操作.需要使用连接池对其进行优化.

程序初始化的时候,初始化多个连接,将多个连接放入到池(集合)中.每次获取的时候,都可以直接从连接池中进行获取.使用结束以后,将连接归还到池中.

  1. 程序一开始就创建一定数量的连接,放在一个容器(集合)中,这个容器称为连接池。

  2. 使用的时候直接从连接池中取一个已经创建好的连接对象, 使用完成之后 归还到池子

  3. 如果池子里面的连接使用完了, 还有程序需要使用连接, 先等待一段时间(eg: 3s), 如果在这段时间之内有连接归还, 就拿去使用; 如果还没有连接归还, 新创建一个, 但是新创建的这一个不会归还了(销毁)

  4. 集合选择LinkedList

    • 增删比较快

    • LinkedList里面的removeFirst()和addLast()方法和连接池的原理吻合

2.自定义连接池-初级版本

  • 创建连接池类

  • 在连接池类中,定义一个LinkedList集合(表示连接池)

  • 在连接池类的静态代码块中,创建固定数量的连接,并存储到LinkedList集合中

  • 提供一个公共的非静态方法来获取连接对象(getAbc)

  • 提供一个公共的非静态方法来归还连接对象(addBack)

  • 提供一个公共的静态方法来获取连接池中连接的数量

package com.jcli.demo02_自定义连接池初级版;

import com.jcli.utils.JDBCUtils;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedList;

/**
 * - 创建连接池类
 */
public class MyDataSource01 {
    //- 在连接池类中,定义一个LinkedList集合(表示连接池)
    private static LinkedList<Connection> pools = new LinkedList<>();

    //- 在连接池类的静态代码块中,创建固定数量的连接,并存储到LinkedList集合中
    static {
        for (int i = 0; i < 6; i++) {
            try {
                //获得连接
                Connection connection = JDBCUtils.getConnection();
                //把连接添加到连接池
                pools.add(connection);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //- 提供一个公共的非静态方法来获取连接对象(getAbc)
    public Connection getAbc() {
        Connection connection = pools.removeFirst();
        return connection;
    }

    //- 提供一个公共的非静态方法来归还连接对象(addBack)
    public void addBack(Connection connection) {
        pools.addLast(connection);
    }

    //- 提供一个公共的静态方法来获取连接池中连接的数量
    public static int size() {
        return pools.size();
    }
}

测试:

// 1.创建连接池对象
// 2.获得连接
// 3.预编译sql语句,得到预编译对象
// 4.设置参数
// 5.执行sql语句,处理结果
// 取数据
// 6.归还连接
// 7.释放资源
package com.jcli.demo02_自定义连接池初级版;

import com.jcli.utils.JDBCUtils;

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

public class Test {
    public static void main(String[] args) throws SQLException {
        // 1.创建连接池对象
        MyDataSource01 dataSource01 = new MyDataSource01();
        System.out.println("获得连接之前:"+MyDataSource01.size());
        // 2.获得连接
        Connection connection = dataSource01.getAbc();
        System.out.println("获得连接之后:"+MyDataSource01.size());
        // 3.预编译sql语句,得到预编译对象
        String sql = "select * from user where id = ?";
        PreparedStatement ps = connection.prepareStatement(sql);
        // 4.设置参数
        ps.setInt(1,1);
        // 5.执行sql语句,处理结果
        ResultSet resultSet = ps.executeQuery();
        // 取数据
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");
            String password = resultSet.getString("password");
            String nickname = resultSet.getString("name");
        }
        System.out.println("归还连接之前:"+MyDataSource01.size());
        // 6.归还连接
        dataSource01.addBack(connection);
        System.out.println("归还连接之后:"+MyDataSource01.size());
        // 7.释放资源
        JDBCUtils.release(resultSet,ps,null);
    }
}

3.自定义连接池-进阶版本

实现接口DataSource,重写获取方法getConnection

  • 创建连接池类, 实现DataSource接口,重写方法

  • 在连接池类中,定义一个LinkedList集合(表示连接池)

  • 在连接池类的静态代码块中,创建固定数量的连接,并存储到LinkedList集合中

  • 使用重写的方法getConnection,来获取连接对象

  • 提供一个公共的非静态方法来归还连接对象(addBack)

  • 提供一个公共的静态方法来获取连接池中连接的数量

package com.jcli.demo03_自定义连接池进阶版;

import com.jcli.utils.JDBCUtils;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;

/**
 * - 创建连接池类
 */
public class MyDataSource02 implements DataSource {
    //- 在连接池类中,定义一个LinkedList集合(表示连接池)
    private static LinkedList<Connection> pools = new LinkedList<>();

    //- 在连接池类的静态代码块中,创建固定数量的连接,并存储到LinkedList集合中
    static {
        for (int i = 0; i < 6; i++) {
            try {
                //获得连接
                Connection connection = JDBCUtils.getConnection();
                //把连接添加到连接池
                pools.add(connection);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //- 提供一个公共的非静态方法来获取连接对象(getAbc)
    /*public Connection getAbc() {
        Connection connection = pools.removeFirst();
        return connection;
    }*/

    //- 提供一个公共的非静态方法来归还连接对象(addBack)
    public void addBack(Connection connection) {
        pools.addLast(connection);
    }

    //- 提供一个公共的静态方法来获取连接池中连接的数量
    public static int size() {
        return pools.size();
    }

    //- 重写getConnection方法,获得链接
    @Override
    public Connection getConnection() throws SQLException {
        Connection connection = pools.removeFirst();
        return connection;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

测试:

package com.jcli.demo02_自定义连接池初级版;

import com.jcli.utils.JDBCUtils;

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

public class Test {
    public static void main(String[] args) throws SQLException {
        // 1.创建连接池对象
        MyDataSource01 dataSource01 = new MyDataSource01();
        System.out.println("获得连接之前:"+MyDataSource01.size());
        // 2.获得连接
        Connection connection = dataSource01.getAbc();
        System.out.println("获得连接之后:"+MyDataSource01.size());
        // 3.预编译sql语句,得到预编译对象
        String sql = "select * from user where id = ?";
        PreparedStatement ps = connection.prepareStatement(sql);
        // 4.设置参数
        ps.setInt(1,1);
        // 5.执行sql语句,处理结果
        ResultSet resultSet = ps.executeQuery();
        // 取数据
        while (resultSet.next()){
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");
            String password = resultSet.getString("password");
            String nickname = resultSet.getString("name");
        }
        System.out.println("归还连接之前:"+MyDataSource01.size());
        // 6.归还连接
        dataSource01.addBack(connection);
        System.out.println("归还连接之后:"+MyDataSource01.size());
        // 7.释放资源
        JDBCUtils.release(resultSet,ps,null);
    }
}

4.装饰者模式

  • 作用:改写已存在的类的某个方法或某些方法

  • 条件:

    • 装饰类和被装饰类要实现同一个接口

    • 装饰类里面要拿到被装饰类的引用

    • 对需要增强的方法进行增强

    • 对不需要增强的方法就调用被装饰类中原有的方法

package com.jcli.demo04_装饰者模式;

public interface Star {
    void sing();
    void dance();
}
package com.jcli.demo04_装饰者模式;

// 被装饰类
public class CiVi implements Star {
    @Override
    public void sing() {
        System.out.println("CiVi在唱小星星~~~");
    }

    @Override
    public void dance() {
        System.out.println("CiVi在跳绳~~~");
    }
}

package com.jcli.demo04_装饰者模式;
// 装饰类
public class CiViWrapper implements Star {
    Star star;

    public CiViWrapper(Star star) {
        this.star = star;
    }

    @Override
    public void sing() {
        System.out.println("CiVi在唱小星星~~~");
        System.out.println("CiVi在唱十年~~~");
        System.out.println("CiVi在唱绿光~~~");
    }

    @Override
    public void dance() {
        star.dance();
    }
}
package com.jcli.demo04_装饰者模式;

public class Test {
    public static void main(String[] args) {
        CiVi ciVi = new CiVi();
        CiViWrapper cvw = new CiViWrapper(ciVi);
        cvw.sing();
        cvw.dance();
    }
}

5.自定义连接池-终极版本

  • 创建增强的连接类,对close方法进行增强,其余方法依然调用原有的连接对象的方法

  • 创建连接池类, 实现DataSource接口,重写方法

  • 在连接池类中,定义一个LinkedList集合(表示连接池)

  • 在连接池类的静态代码块中,创建固定数量的连接,并存储到LinkedList集合中

  • 使用重写的方法getConnection,来获取连接对象----->增强的连接对象

  • 提供一个公共的静态方法来获取连接池中连接的数量

  • 与进阶版的区别:

    • 连接池类中不需要提供归还连接的方法

    • getConnection获得连接的方法不再返回被增强的连接对象,而是返回增强的连接对象

实现

//装饰类
//获取被装饰的引用
//创建linkedList集合
//对需要增强的方法增强~~~归还连接
//不需要增强的直接调用~~~被装饰类
//创建连接池类
//- 重写getConnection方法,获得链接
// 返回增强的连接对象
//- 取消归还连接对象(addBack)方法
package com.jcli.demo05_自定义连接池终极版;

import java.sql.*;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

// 装饰类
public class MyConnection implements Connection {
    //获取被装饰的引用
    Connection connection;
    //创建linkedList集合
    LinkedList<Connection> pools;

    public MyConnection(Connection connection, LinkedList<Connection> pools) {
        this.connection = connection;
        this.pools = pools;
    }

    @Override
    public void close() throws SQLException {
        // 对需要增强的方法进行增强----归还连接
        pools.addLast(connection);
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        // 对不需要增强的方法就调用被装饰类中原有的方法
        return connection.createStatement();
    }

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        // 对不需要增强的方法就调用被装饰类中原有的方法
        return connection.prepareStatement(sql);
    }


    @Override
    public Statement createStatement() throws SQLException {
        return null;
    }


    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        return null;
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
        return null;
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {

    }

    @Override
    public boolean getAutoCommit() throws SQLException {
        return false;
    }

    @Override
    public void commit() throws SQLException {

    }

    @Override
    public void rollback() throws SQLException {

    }


    @Override
    public boolean isClosed() throws SQLException {
        return false;
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
        return null;
    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {

    }

    @Override
    public boolean isReadOnly() throws SQLException {
        return false;
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {

    }

    @Override
    public String getCatalog() throws SQLException {
        return null;
    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {

    }

    @Override
    public int getTransactionIsolation() throws SQLException {
        return 0;
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
        return null;
    }

    @Override
    public void clearWarnings() throws SQLException {

    }


    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        return null;
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
        return null;
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {

    }

    @Override
    public void setHoldability(int holdability) throws SQLException {

    }

    @Override
    public int getHoldability() throws SQLException {
        return 0;
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
        return null;
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        return null;
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {

    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {

    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return null;
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
        return null;
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
        return null;
    }

    @Override
    public Clob createClob() throws SQLException {
        return null;
    }

    @Override
    public Blob createBlob() throws SQLException {
        return null;
    }

    @Override
    public NClob createNClob() throws SQLException {
        return null;
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
        return null;
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
        return false;
    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {

    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {

    }

    @Override
    public String getClientInfo(String name) throws SQLException {
        return null;
    }

    @Override
    public Properties getClientInfo() throws SQLException {
        return null;
    }

    @Override
    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
        return null;
    }

    @Override
    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
        return null;
    }

    @Override
    public void setSchema(String schema) throws SQLException {

    }

    @Override
    public String getSchema() throws SQLException {
        return null;
    }

    @Override
    public void abort(Executor executor) throws SQLException {

    }

    @Override
    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {

    }

    @Override
    public int getNetworkTimeout() throws SQLException {
        return 0;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}

6.C3P0连接池

1.通过硬编码来编写【了解】

  • 拷贝c3p0的jar包到模块下

  • 创建c3p0连接池对象

  • 设置连接参数

  • 获得连接对象

  • 预编译sql语句,得到预编译对象

  • 设置sql语句参数

  • 执行sql语句,处理结果

  • 释放资源

package com.jcli.demo06_C3P0连接池;

import com.jcli.utils.JDBCUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;

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

public class Test01 {
    public static void main(String[] args) throws Exception {
        //- 拷贝c3p0的jar包到模块下
        //        - 创建c3p0连接池对象
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        //        - 设置连接参数
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jcli_ee");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setInitialPoolSize(5);
        //        - 获得连接对象
        Connection connection = dataSource.getConnection();
        //        - 预编译sql语句,得到预编译对象
        String sql = "select * from user where id = ?";
        PreparedStatement ps = connection.prepareStatement(sql);
        //        - 设置sql语句参数
        ps.setInt(1, 1);
        //        - 执行sql语句,处理结果
        ResultSet resultSet = ps.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getInt("id"));
            System.out.println(resultSet.getString("username"));
            System.out.println(resultSet.getString("password"));
            System.out.println(resultSet.getString("name"));
        }
        //        - 释放资源
        JDBCUtils.release(resultSet, ps, connection);
    }
}

2.通过配置文件来编写

- 拷贝c3p0的jar包到模块下
- 拷贝c3p0-config.xml配置文件拷贝到模块的src路径下
  - **c3p0-config.xml配置文件的文件名不能修改,必须为c3p0-config.xml**
  - **c3p0-config.xml配置文件的路径必须在src路径下**
  - **c3p0-config.xml配置文件中property标签的name属性值不能修改**
- 创建c3p0连接池对象
- 获得连接对象
- 预编译sql语句,得到预编译对象
- 设置sql语句参数
- 执行sql语句,处理结果
- 释放资源

package com.jcli.demo06_C3P0连接池;

import com.jcli.utils.JDBCUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;

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

public class Test02 {
    public static void main(String[] args) throws SQLException {
        //- 拷贝c3p0的jar包到模块下
        //        - 拷贝c3p0-config.xml配置文件拷贝到模块的src路径下
        //        - **c3p0-config.xml配置文件的文件名不能修改,必须为c3p0-config.xml**
        //- **c3p0-config.xml配置文件的路径必须在src路径下**
        //- **c3p0-config.xml配置文件中property标签的name属性值不能修改**
        //- 创建c3p0连接池对象
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        //        - 获得连接对象
        Connection connection = dataSource.getConnection();
        //        - 预编译sql语句,得到预编译对象
        String sql = "select * from user where id = ?";
        PreparedStatement ps = connection.prepareStatement(sql);
        //        - 设置sql语句参数
        ps.setInt(1, 1);
        //        - 执行sql语句,处理结果
        ResultSet resultSet = ps.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getInt("id"));
            System.out.println(resultSet.getString("username"));
            System.out.println(resultSet.getString("password"));
            System.out.println(resultSet.getString("name"));
        }
        //        - 释放资源
        JDBCUtils.release(resultSet, ps, connection);
    }
}

3.使用c3p0改写工具类

整个程序只需要创建一个连接池对象,其余地方直接使用这个唯一的连接池对象获得连接即可

- 创建唯一的连接池对象---->private static final修饰
- 提供一个获取连接池对象的静态方法
- 提供一个获取连接的静态方法
- 提供一个释放资源的静态方法
package com.jcli.utils;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class C3P0Utils {
    //    - 创建唯一的连接池对象---->private static final修饰
    private static final ComboPooledDataSource DATA_SOURCE = new ComboPooledDataSource();

    //- 提供一个获取连接池对象的静态方法
    public static DataSource getDataSource() {
        return DATA_SOURCE;
    }

    //- 提供一个获取连接的静态方法
    public static Connection getConnection() throws SQLException {
        return DATA_SOURCE.getConnection();
    }

    //- 提供一个释放资源的静态方法
    public static void release(ResultSet resultSet, Statement statement, Connection connection) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}
package com.jcli.demo06_C3P0连接池;

import com.jcli.utils.C3P0Utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;

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

public class Test3 {
    public static void main(String[] args) throws Exception{
        //- 创建c3p0连接池对象
        DataSource dataSource = C3P0Utils.getDataSource();

        //- 获得连接对象
        Connection connection = dataSource.getConnection();

        //- 预编译sql语句,得到预编译对象
        String sql = "select * from user where id = ?";
        PreparedStatement ps = connection.prepareStatement(sql);

        //- 设置sql语句参数
        ps.setInt(1,1);

        //- 执行sql语句,处理结果
        ResultSet resultSet = ps.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getInt("id"));
            System.out.println(resultSet.getString("username"));
            System.out.println(resultSet.getString("password"));
            System.out.println(resultSet.getString("name"));
        }
        //- 释放资源
        C3P0Utils.release(resultSet,ps,connection);
    }
}

7.DRUID连接池

1.通过硬编码方式【了解】

- 导入druid的jar包到模块中
- 创建druid的连接池对象
- 设置连接参数
- 获得连接对象
- 预编译sql语句,得到预编译对象
- 设置sql语句参数
- 执行sql语句,处理结果
- 释放资源
package com.jcli.demo07_DRUID连接池;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.jcli.utils.JDBCUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;

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

public class Test01 {
    public static void main(String[] args) throws Exception {
        //- 导入druid的jar包到模块中
        //- 创建druid的连接池对象
        DruidDataSource dataSource = new DruidDataSource();
        //        - 设置连接参数
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/jcli_ee");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        //        - 获得连接对象
        DruidPooledConnection connection = dataSource.getConnection();
        //        - 预编译sql语句,得到预编译对象
        String sql = "select * from user where id = ?";
        PreparedStatement ps = connection.prepareStatement(sql);
        //        - 设置sql语句参数
        ps.setInt(1, 1);
        //        - 执行sql语句,处理结果
        ResultSet resultSet = ps.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getInt("id"));
            System.out.println(resultSet.getString("username"));
            System.out.println(resultSet.getString("password"));
            System.out.println(resultSet.getString("name"));
        }
        //        - 释放资源
        JDBCUtils.release(resultSet, ps, connection);
    }
}

2.通过配置文件方式

- 拷贝druid的jar包到模块下
- 拷贝druid.properties配置文件拷贝到模块的src路径下
  - druid.properties配置文件的文件名可以修改
  - druid.properties配置文件的路径建议在src路径下
  - druid.properties配置文件中的键名不能修改
- 创建druid连接池对象,传入Properties对象
- 获得连接对象
- 预编译sql语句,得到预编译对象
- 设置sql语句参数
- 执行sql语句,处理结果
- 释放资源
package com.jcli.demo07_DRUID连接池;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.jcli.utils.JDBCUtils;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

public class Test02 {
    public static void main(String[] args) throws Exception {
        //- 拷贝druid的jar包到模块下
        //- 拷贝druid.properties配置文件拷贝到模块的src路径下
        //  - druid.properties配置文件的文件名可以修改
        //  - druid.properties配置文件的路径建议在src路径下
        //  - druid.properties配置文件中的键名不能修改

        // 创建properties对象,加载druid.properties配置文件
        Properties pro = new Properties();
        InputStream is = Test02.class.getClassLoader().getResourceAsStream("druid.properties");
        pro.load(is);
        //- 创建druid连接池对象,传入Properties对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(pro);
        //        - 设置连接参数
        //dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        //dataSource.setUrl("jdbc:mysql://localhost:3306/jcli_ee");
        //dataSource.setUsername("root");
        //dataSource.setPassword("root");
        //        - 获得连接对象
        Connection connection = dataSource.getConnection();
        //        - 预编译sql语句,得到预编译对象
        String sql = "select * from user where id = ?";
        PreparedStatement ps = connection.prepareStatement(sql);
        //        - 设置sql语句参数
        ps.setInt(1, 1);
        //        - 执行sql语句,处理结果
        ResultSet resultSet = ps.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getInt("id"));
            System.out.println(resultSet.getString("username"));
            System.out.println(resultSet.getString("password"));
            System.out.println(resultSet.getString("name"));
        }
        //        - 释放资源
        JDBCUtils.release(resultSet, ps, connection);
    }
}

3.Druid工具类的制作

- 创建连接池成员变量
- 在静态代码块中加载配置文件,创建druid连接池对象
- 提供一个获取连接池对象的静态方法
- 提供一个获取连接的静态方法
- 提供一个释放资源的静态方法
package com.jcli.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.jcli.demo07_DRUID连接池.Test02;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class DruidUtils {
    //    - 创建连接池成员变量
    private static DataSource dataSource;

    //- 在静态代码块中加载配置文件,创建druid连接池对象
    static {
        try {

            Properties pro = new Properties();
            InputStream is = Test02.class.getClassLoader().getResourceAsStream("druid.properties");
            pro.load(is);

            //- 创建druid连接池对象,传入Properties对象
            dataSource = DruidDataSourceFactory.createDataSource(pro);

        } catch (Exception e) {

        }
    }

    //- 提供一个获取连接池对象的静态方法
    public static DataSource getDataSource() {
        return dataSource;
    }

    //- 提供一个获取连接的静态方法
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    //- 提供一个释放资源的静态方法
    public static void release(ResultSet resultSet, Statement statement, Connection connection) {

        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }


}
package com.jcli.demo07_DRUID连接池;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.jcli.utils.DruidUtils;
import com.jcli.utils.JDBCUtils;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

public class Test03 {
    public static void main(String[] args) throws Exception {
        //获得连接池对象
        DataSource dataSource = DruidUtils.getDataSource();
        /*// 创建properties对象,加载druid.properties配置文件
        Properties pro = new Properties();
        InputStream is = Test03.class.getClassLoader().getResourceAsStream("druid.properties");
        //pro.load(is);
        //- 创建druid连接池对象,传入Properties对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(pro);*/
        //        - 获得连接对象
        Connection connection = dataSource.getConnection();
        //        - 预编译sql语句,得到预编译对象
        String sql = "select * from user where id = ?";
        PreparedStatement ps = connection.prepareStatement(sql);
        //        - 设置sql语句参数
        ps.setInt(1, 1);
        //        - 执行sql语句,处理结果
        ResultSet resultSet = ps.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getInt("id"));
            System.out.println(resultSet.getString("username"));
            System.out.println(resultSet.getString("password"));
            System.out.println(resultSet.getString("name"));
        }
        //        - 释放资源
        JDBCUtils.release(resultSet, ps, connection);
    }
}

8.DBUtils完成增删改

- 导入DButils的jar包---->mysql驱动包,第三方数据库连接池的jar包,配置文件,工具类
- 创建QueryRunner对象,传入连接池对象
- 调用update方法执行sql语句
package com.jcli.demo08_DBUtils完成增删改;

import com.jcli.utils.C3P0Utils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;

import java.sql.SQLException;

public class TestDemo {
//- 导入DButils的jar包---->mysql驱动包,第三方数据库连接池的jar包,配置文件,工具类
//- 创建QueryRunner对象,传入连接池对象
//- 调用update方法执行sql语句
    QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
    @Test
    public void add() throws SQLException {
        String sql = "insert into user values(null,?,?,?)";
        int rows = queryRunner.update(sql, "tq", "123", "田七");
        System.out.println("insert受影响的行数:" + rows);
    }
    @Test
    public void update() throws SQLException {
        String sql = "update user set password=? where name=?";
        int rows = queryRunner.update(sql,  "11123", "田七");
        System.out.println("update受影响的行数:" + rows);
    }
    @Test
    public void delete() throws SQLException {
        String sql = "delete from user where id = ?";
        int rows = queryRunner.update(sql,  10);
        System.out.println("delete受影响的行数:" + rows);
    }

}

9.DBUtils完成查询

查询一条记录(使用ArrayHandler,使用BeanHandler,使用MapHandler)

package com.jcli.demo09_DBUtils完成查询;

import com.jcli.bean.User;
import com.jcli.utils.C3P0Utils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.junit.Test;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.Map;

//查询一条记录
public class Test01 {
    //- 创建QueryRunner对象,传入连接池对象
    QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());

    // 查询结果为一条记录的封装成数组
    @Test
    public void selectById1() throws SQLException {
        String sql = "select * from user where id = ?";
        Object[] arr = queryRunner.query(sql, new ArrayHandler(), 1);
        System.out.println(Arrays.toString(arr));
    }

    //    查询结果记录为一条记录的封装成javabean对象
    @Test
    public void selectById2() throws SQLException {
        String sql = "select * from user where id = ?";
        User arr = queryRunner.query(sql, new BeanHandler<User>(User.class), 1);
        System.out.println(arr);
    }

    //    查询结果为一条记录的封装成map集合
    @Test
    public void selectById3() throws SQLException {
        String sql = "select * from user where id = ?";
        Map<String, Object> map = queryRunner.query(sql, new MapHandler(), 1);
        System.out.println(map);
    }
}

查询多条数据封装到List集合中(使用ArrayListHandler,使用BeanListHandler,使用MapListHandler)

package com.jcli.demo09_DBUtils完成查询;

import com.jcli.bean.User;
import com.jcli.utils.C3P0Utils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import org.junit.Test;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

//查询多条记录
public class Test02 {
    //- 创建QueryRunner对象,传入连接池对象
    QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());

    // 查询结果为多条记录的封装成list集合,类型Object数组
    @Test
    public void selectByAll1() throws SQLException {
        String sql = "select * from user ";
        List<Object[]> list = queryRunner.query(sql, new ArrayListHandler());
        for (Object[] arr : list) {
            System.out.println(Arrays.toString(arr));
        }
    }

    //    查询结果记录为多条记录的封装成list集合,类型javabean对象
    @Test
    public void selectByAll2() throws SQLException {
        String sql = "select * from user ";
        List<User> list = queryRunner.query(sql, new BeanListHandler<User>(User.class) );
        for (User user : list) {
            System.out.println(user);
        }
    }

    //    查询结果为多条记录的封装成list集合,类型+map集合
    @Test
    public void selectByAll3() throws SQLException {
        String sql = "select * from user ";
        List<Map<String, Object>> list = queryRunner.query(sql, new MapListHandler());
        for (Map<String, Object> map : list) {
            System.out.println(map);
        }
    }
}

查询单个数据(使用ScalarHandler())

package com.jcli.demo09_DBUtils完成查询;

import com.jcli.bean.User;
import com.jcli.utils.C3P0Utils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

//查询单个数据(使用ScalarHandler())
public class Test03 {
    //- 创建QueryRunner对象,传入连接池对象
    QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
    @Test
    public void selectByAll1() throws SQLException {
        String sql = "select count(*) from user ";
        Long count = (Long) queryRunner.query(sql, new ScalarHandler());
        System.out.println(count);
    }
}

查询单列多个值(使用ColumnListHandler)

package com.jcli.demo09_DBUtils完成查询;

import com.jcli.utils.C3P0Utils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;

import java.sql.SQLException;
import java.util.List;

//查询单列多个值(使用ColumnListHandler)
public class Test04 {
    //- 创建QueryRunner对象,传入连接池对象
    QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
    @Test
    public void selectByAll1() throws SQLException {
        String sql = "select name from user ";
        List<Object> list = queryRunner.query(sql,new ColumnListHandler());
        System.out.println(list);
    }
}

10.元数据

参数元数据

package com.jcli.demo10_自定义DBUtils;

import com.jcli.utils.JDBCUtils;

import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;

//参数元数据
public class Test01 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JDBCUtils.getConnection();
        String sql = "select * from user where username = ? and password = ?";
        PreparedStatement ps = connection.prepareStatement(sql);
        //- 获取参数的元数据对象

        ParameterMetaData pmd = ps.getParameterMetaData();
        //- 根据参数的元数据对象 获取 参数的元数据
        System.out.println("获取参数计数:"+pmd.getParameterCount());
        //Parameter metadata not available for the given statement
        System.out.println("获取参数类名称"+pmd.getParameterClassName(1));
    }
}

结果集元素数据

package com.jcli.demo10_自定义DBUtils;

import com.jcli.utils.JDBCUtils;

import java.sql.*;

// 结果集元素数据
public class Test02 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JDBCUtils.getConnection();
        String sql = "select * from user";
        PreparedStatement ps = connection.prepareStatement(sql);
        ResultSet resultSet = ps.executeQuery();
        // 获得结果集元数据对象
        ResultSetMetaData rmd = resultSet.getMetaData();

        // 使用结果集元数据对象 获得 结果集的元数据(列的个数,列的名称,类型...)
        int columnCount = rmd.getColumnCount();
        System.out.println("结果集中列的个数:"+columnCount);
        // 循环遍历获取列名,列的类型
        for (int i = 1; i <= columnCount; i++) {
            System.out.println("结果集中列的名称:"+rmd.getColumnName(i));
            System.out.println("结果集中列的sql类型:"+rmd.getColumnTypeName(i));
            System.out.println("结果集中列的java类型:"+rmd.getColumnClassName(i));
            System.out.println("----------------");
        }
    }
}

11.自定义DBUtils增删改

- 创建MyQueryRunner类
- 定义一个DataSource成员变量
- 定义一个有参构造方法,空参构造方法
- 定义一个update(String sql,Object... args)完成增删改操作
package com.jcli.demo11_自定义DBUtils增删改;

import com.jcli.utils.JDBCUtils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * - 创建MyQueryRunner类
 */
public class MyQueryRunner {
    //    * - 定义一个DataSource成员变量
    private DataSource dataSource;

    //    * - 定义一个有参构造方法,空参构造方法
    public MyQueryRunner() {
    }

    public MyQueryRunner(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    //    * - 定义一个update(String sql,Object... args)完成增删改操作
    public int update(String sql, Object... args) throws SQLException {
        //- 1.注册驱动,获得连接
        Connection connection = dataSource.getConnection();
        //        - 2.预编译sql语句,得到预编译对象
        PreparedStatement ps = connection.prepareStatement(sql);
        //        - 3.设置参数
        // 3.1 获得参数的元数据对象
        ParameterMetaData pmd = ps.getParameterMetaData();
        // 3.2 通过参数元数据对象获取参数的个数
        int parameterCount = pmd.getParameterCount();
        // 3.3 循环遍历赋值
        for (int i = 0; i < parameterCount; i++) {
            ps.setObject(i + 1, args[i]);
        }
        //        - 4.执行sql语句,处理结果
        int rows = ps.executeUpdate();
        //        - 5.释放资源
        JDBCUtils.release(null, ps, connection);
        return rows;
    }

}
package com.jcli.demo11_自定义DBUtils增删改;

import com.jcli.utils.C3P0Utils;
import org.junit.Test;

import java.sql.SQLException;

public class TestDemo {
    //- 导入DButils的jar包---->mysql驱动包,第三方数据库连接池的jar包,配置文件,工具类
//- 创建QueryRunner对象,传入连接池对象
    MyQueryRunner queryRunner = new MyQueryRunner(C3P0Utils.getDataSource());

    //- 调用update方法执行sql语句
    @Test
    public void add() throws SQLException {
        String sql = "insert into user values(null,?,?,?)";
        int rows = queryRunner.update(sql, "tq", "123", "田七");
        System.out.println("insert受影响的行数:" + rows);
    }

    @Test
    public void update() throws SQLException {
        String sql = "update user set password=? where name=?";
        int rows = queryRunner.update(sql, "11123", "田七");
        System.out.println("update受影响的行数:" + rows);
    }

    @Test
    public void delete() throws SQLException {
        String sql = "delete from user where id = ?";
        int rows = queryRunner.update(sql, 10);
        System.out.println("delete受影响的行数:" + rows);
    }

}

 代码:

https://gitee.com/li-ear/dbutils.git