击穿JDBC 例子详解 数据库连接池+DBUtil+JDBC+Servlet +jsp增删改查案例(二)全

数据库连接池

先来看一个我们平时查询普通的流程是怎样的

 

 上面是一个请求查询的方式,实际项目请求有很多个,不同用户发起请求,每次都要进行连接,连接完后又释放掉,十分浪费资源,那有什么办法楠

可以使⽤数据库连接池解决这⼀问题。 数据库连接池的基本思想就是为数据库建⽴⼀个缓冲池,预先向缓冲池中放⼊⼀定数量的连接对象,当 需要获取数据库连接的时候,只需要从缓冲池中取出⼀个对象,⽤完之后再放回到缓冲池中,供下⼀次 请求使⽤,做到了资源的重复利⽤,允许程序重复使⽤⼀个现有的数据库连接对象,⽽不需要重新创 建。 当数据库连接池中没有空闲的连接时,新的请求就会进⼊等待队列,等待其他线程释放连接

 相当于在java程序与数据库之间放一个连接池,来画个图

 需要的时候就从数据库连接池拿出来就行了,不要了又放回去

怎么实现呢?

 JDBC 的数据库连接池使⽤ javax.sql.DataSource 接⼝来完成的,DataSource 是 Java 官⽅提供的接 ⼝,使⽤的时候开发者并不需要⾃⼰来实现该接⼝,可以使⽤第三⽅的⼯具,C3P0 是⼀个常⽤的第三 ⽅实现,实际开发中直接使⽤ C3P0 即可完成数据库连接池的操作

 意思就是有人在一个类里面已经把那些接口实现了,我们只需要创建对象拿来用就行了

 导包

 

 需要用到的表

 

 public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            //创建C3P0对象
            ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
            //获取驱动
            comboPooledDataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
            //获取连接
            comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/student?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai");
            comboPooledDataSource.setUser("root");
            comboPooledDataSource.setPassword("123456");
            connection = comboPooledDataSource.getConnection();

            //用?来表示
            String sql = "select ename from emp where ename like ?";
            //取得数据库操作对象
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"_A%");
            //执行查询语句
            resultSet = preparedStatement.executeQuery();

            //输出
            while (resultSet.next()){
                System.out.println(resultSet.getString("ename"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

这样也是能查到的

为了不让太多代码写在Java程序中,也为了便于更改,我们将文件写在xml中

实际开发,将 C3P0 的配置信息定义在 xml ⽂件中,Java 程序只需要加载配置⽂件即可完成数据库连接 池的初始化操作。

1、配置⽂件的名字必须是 c3p0-config.xml

2、初始化 ComboPooledDataSource 时,传⼊的参数必须是 c3p0-config.xml 中 named-config 标签 的 name 属性值。

  

 看看我xml文件的位置     xml中&代表&

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <named-config name="studentc3p0">
        <!-- 指定连接数据源的基本属性 -->
        <property name="user">root</property>
        <property name="password">123456</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/student?
            useUnicode=true&amp;characterEncoding=UTF-8</property>
        <property name="acquireIncrement">5</property>
        <!-- 初始化数据库连接池时连接的数量 -->
        <property name="initialPoolSize">20</property>
        <!-- 数据库连接池中的最⼩的数据库连接数 -->
        <property name="minPoolSize">2</property>
        <!-- 数据库连接池中的最⼤的数据库连接数 -->
        <property name="maxPoolSize">40</property>
    </named-config>
</c3p0-config>

那Java文件怎么写呢

public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            //创建C3P0对象
            ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("studentc3p0");

            //获取连接
            connection = comboPooledDataSource.getConnection();

            //用?来表示
            String sql = "select ename from emp where ename like ?";
            //取得数据库操作对象
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"_A%");
            //执行查询语句
            resultSet = preparedStatement.executeQuery();

            //输出
            while (resultSet.next()){
                System.out.println(resultSet.getString("ename"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                resultSet.close();
                preparedStatement.close();
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
    }


DBUtils

DBUtils 可以帮助开发者完成数据的封装(结果集到 Java 对象的映射)

顾名思义,当然是方便用户呀,我们来几个例子

 和数据库常量池一样,DBUtils提供了实现类,我们直接创建对象然后调用方法就行了

用到的表,为了把学生对象和表元素对应,我们把t_user拿来使用

 

 

写一个学生类,把我查询到的放在学生类对象里面再输出(注意有参无参构造和toString方法加上

 

public class Student {
    private Integer id;
    private String username;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", username='" + username + '\'' +
                '}';
    }

    public Student() {
    }

    public Student(Integer id, String username) {
        this.id = id;
        this.username = username;
    }

}

 最初的查询办法

public static void main(String[] args) {
        System.out.println(findBId());
    }


    public static Student findBId(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        Student student = null;
        try {
            //创建C3P0对象
            ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("1c3p0");
            //获取连接
            connection = comboPooledDataSource.getConnection();
            //用?来表示
            String sql = "select * from t_user where id = 1";
            //取得数据库操作对象
            preparedStatement = connection.prepareStatement(sql);
            //执行查询语句
            resultSet = preparedStatement.executeQuery();
            //输出
            while (resultSet.next()) {
                Integer id = resultSet.getInt(1);
                String username = resultSet.getString(2);
                student = new Student(id,username);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                resultSet.close();
                preparedStatement.close();
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return student;
    }

 获取连接后我们有更简单的方法来处理sql语句后面的那部分

也就是这一部分

preparedStatement = connection.prepareStatement(sql);
            
            resultSet = preparedStatement.executeQuery();
            
            while (resultSet.next()) {
                Integer id = resultSet.getInt(1);
                String username = resultSet.getString(2);
                student = new Student(id,username);
            }

 怎么做呢? 先把包导进来,包可以取网上下载

 拿到数据怎么办楠,用下面的实现类来处理,查询多条记录就要用到第二个第三个了

 看得出来是用来处理结果集的

public static Student findDBUtils(){
        //创建C3P0对象
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("1c3p0");
        Connection connection = null;
        Student student = null;
        try {
            connection = comboPooledDataSource.getConnection();
            String sql = "select * from t_user where id = 1";
            //使用DBUtils提供的类
            QueryRunner queryRunner = new QueryRunner();
            student = queryRunner.query(connection,sql,new BeanHandler<>(Student.class));
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return student;
    }

 使用DBUtils提供的类调用query方法来执行,具体可以自己看看query方法的源码,把结果处理都自己完成了。

  ResultSetHandler rsh 便是我们上面的new BeanHandler(Student.class)

 private <T> T query(Connection conn, boolean closeConn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
        if (conn == null) {
            throw new SQLException("Null connection");
        } else if (sql == null) {
            if (closeConn) {
                this.close(conn);
            }

            throw new SQLException("Null SQL statement");
        } else if (rsh == null) {
            if (closeConn) {
                this.close(conn);
            }

            throw new SQLException("Null ResultSetHandler");
        } else {
            PreparedStatement stmt = null;
            ResultSet rs = null;
            Object result = null;

            try {
                stmt = this.prepareStatement(conn, sql);
                this.fillStatement(stmt, params);
                rs = this.wrap(stmt.executeQuery());
                result = rsh.handle(rs);
            } catch (SQLException var33) {
                this.rethrow(var33, sql, params);
            } finally {
                try {
                    this.close(rs);
                } finally {
                    this.close(stmt);
                    if (closeConn) {
                        this.close(conn);
                    }

                }
            }

            return result;
        }
    }

那后面的Object... params参数是什么意思呢,就是我们自己传入的参数,...代表多个

就拿上面的例子来说,这样也是一样的哦

public static Student findDBUtils(Integer id, String username){
        //创建C3P0对象
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("1c3p0");
        Connection connection = null;
        Student student = null;
        try {
            connection = comboPooledDataSource.getConnection();
            String sql = "select * from t_user where id = ? and username = ?";
            //使用DBUtils提供的类
            QueryRunner queryRunner = new QueryRunner();
            student = queryRunner.query(connection,sql,new BeanHandler<>(Student.class),id,username);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return student;
    }

那我们来讲一下查询多条结果(  new BeanListHandler()  )

List list = queryRunner.query(connection,sql,new BeanListHandler<>(Student.class));
            System.out.println(list);

输出list就行

 

 

上面都是是输出Student对象,我们用什么方式来输出数据库内容楠

这用到new MapHandler()

 代码改成这样就行了

 public static void main(String[] args) {
        findDBUtils();
    }
    public static void findDBUtils(){
        //创建C3P0对象
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("1c3p0");
        Connection connection = null;
        Student student = null;
        try {
            connection = comboPooledDataSource.getConnection();
            String sql = "select * from t_user where id = 1";
            //使用DBUtils提供的类
            QueryRunner queryRunner = new QueryRunner();
            Map map = queryRunner.query(connection,sql,new MapHandler());
            System.out.println(map);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

 那多条结果呢?

 这是什么意思呢

List<Map<String, Object>> list = queryRunner.query(connection,sql,new MapListHandler());
            for(Map<String, Object> map : list){
                System.out.println(map);
            }

就是先把数据取出来先存在Map(String,Object)中,数据类型是默认的,不用更改

再把map存在list集合中

好了,这期就讲到这里,下期我们讲一个JSP + Servlet + JDBC 增删改查的例子

能不能点个赞再走呜呜

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值