小白学习Java第三十二天

今日内容

  1. JDCB封装工具类
  2. DBUTils工具类(第三方)
  3. 连接池
  4. DAO封装

一.JDBC工具类封装

需求说明:

之前的CRUD(增删改查)代码中有一些重复的代码,我们可以将他们抽取出来封装成工具类。

封装的思想可以简化代码开发,提高代码的复用性,提高开发的效率。

封装的思路:

创建配置文件:jdbc.properties

mysql.driver= com.mysql.jdbc.Driver
mysql.url = jdbc:mysql://localhost:3306/studb
mysql.user = root
mysql.password = root

编写JDBC工具类:JDBCUtils

package com.ujiuye.utils;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/*JDBC封装工具类*/
public class JDBCUtils {
    private static Connection conn = null;
    //定义静态代码块读取配置文本创建连接
    static {
        //1.读取配置文件
        Properties properties = new Properties();
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("day10/src/jdbc.properties");
            properties.load(fis);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //2.读取属性值
        String driver = properties.getProperty("mysql.driver");
        String url = properties.getProperty("mysql.url");
        String user = properties.getProperty("mysql.user");
        String password = properties.getProperty("mysql.password");
        System.out.println(driver+"-"+url+"-"+user+"-"+password);
        try {
            //3.加载驱动
            Class.forName(driver);
            //4.创建连接
            conn = DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取连接
    public  static  Connection getConn(){
        return  conn;
    }
    //释放资源
    public  static void closeAll(ResultSet rs, PreparedStatement pstmt,Connection conn){
        try {
            if(rs!=null){
                rs.close();
            }
            if (pstmt != null){
                pstmt.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

}

测试工具类:

public static void main(String[] args) {
    String sql = "INSERT INTO admin(username,PASSWORD) VALUES(?,?)";
    PreparedStatement pstmt = null;
    //调用工具类获取连接对象
    Connection conn = JDBCUtils.getConn();
    try {
        //创建执行SQL语句的对象
        pstmt = conn.prepareStatement(sql);
        //给sql语句中?赋值
        pstmt.setString(1,"xiaoliu");
        pstmt.setString(2,"000");
        //执行SQL语句
        int row = pstmt.executeUpdate();
        System.out.println(row);
    } catch (SQLException e) {
        e.printStackTrace();
    }finally {
        JDBCUtils.closeAll(null,pstmt,conn);
    }
}

二.DBUTils工具类(优化JDBC编程)

  • 概念

commons-dbutils Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。

  • 作用和常用方法

Commons DbUtilsApache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。尤其结合连接池使用效果更为理想。

DbUtils的核心是两个类一个接口:

1DBUtils类:主要为关闭连接,装载JDBC驱动程序之类的常规工作提供方法,都是静态的方法。

2QueryRunner类:为我们提供两个重要方法,调用方法之前需要先创建一个QueryRunner的对象。

为我们提供两个重要方法,调用方法之前需要先创建一个QueryRunner的对象。

QueryRunner qRunner=new QueryRunner();

QueryRunner qRunner=new QueryRunner(new ComboPooledDataSource());

创建对象时需要传入一个连接池的数据源,这里结合c3p0连接池来完成。

  1. qRunner.update(Connection conn,String sql, Object... params)
  2. qRunner.update(String sql, Object... params)

update()方法等价于executeUpdate(),支持DML操作

3qRunner.query(Connection conn,String sql, ResultSetHandler rsh,Object... params)

4qRunner.query(String sql, ResultSetHandler rsh,Object... params)

query()方法等价于executeQuery(),支持DQL操作

3ResultSetHandler接口:用于处理ResultSet结果集,将结果集的的数据转换成不同形式。该接口的实现类有很多:

ArrayHandler

将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值。

ArrayListHandler

将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。

BeanHandler

将结果集中第一条记录封装到一个指定的javaBean中。

BeanListHandler

将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中。

ColumnListHandler

将结果集中指定的列的字段值,封装到一个List集合中。

ScalarHandler

它是用于单列数据查询。例如:select count(*) from users 操作。

MapHandler

将结果集中第一条记录封装到Map集合中,Key代表列名, Value代表该列数据。

MapListHandler

将结果集中每一条记录封装到Map集合中,Key代表列名, Value代表该列数据,Map集合再存储到List集合

javabean封装规则

  1. public修饰类
  2. 成员属性私有private
  3. 属性一定要封装get/set方法
  4. 必须要有无参构造

package com.ujiuye.bean;

public class Admin {
    public Admin() {
    }
    public Admin(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }
    //属性:属性名一定要与数据表中列名保持一致
    private  int id;
    private String username;
    private String password;
    //get/set

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

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

  • 基本使用

使用步骤:

  1. 下载jar包导入项目中   lib/commons-dbutils-1.7.jar
  2. 编写代码

package com.ujiuye.dbutils;

import com.ujiuye.bean.Admin;
import com.ujiuye.utils.JDBCUtils;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;

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

public class TestDBUTils {
    @Test
    public void insert_test(){
        String sql = "INSERT INTO admin(username,PASSWORD) VALUES(?,?)";
        //使用自己封装的工具类获取连接对象
        Connection conn = JDBCUtils.getConn();
        //创建QueryRunner
        QueryRunner runner = new QueryRunner();
        try {
            //调用update(conn,sql,...params)执行添加方法,返回值为影响行数
            int row = runner.update(conn, sql, "lisi", "123");
            System.out.println(row);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                //关闭连接方法
                DbUtils.close(conn);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void  select_one(){
        String sql = "SELECT * FROM admin WHERE id = ?";
        Connection conn = JDBCUtils.getConn();
        QueryRunner runner = new QueryRunner();
        //调用方法执行查询操作
        try {
            Admin admin = runner.query(conn, sql, new BeanHandler<Admin>(Admin.class), 1);
            System.out.println(admin);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                DbUtils.close(conn);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void  select_multi(){
        String sql = "SELECT * FROM admin";
        Connection conn = JDBCUtils.getConn();
        QueryRunner runner = new QueryRunner();
        //调用方法执行查询操作
        try {
            List<Admin> list = runner.query(conn, sql, new BeanListHandler<Admin>(Admin.class));
            for (Admin admin : list) {
                System.out.println(admin);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                DbUtils.close(conn);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    @Test
    public void  scale(){
        String sql = "SELECT count(*) FROM admin";
        Connection conn = JDBCUtils.getConn();
        QueryRunner runner = new QueryRunner();
        //调用方法执行查询操作
        try {
            Object obj = runner.query(conn, sql, new ScalarHandler<>());
            System.out.println(obj);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                DbUtils.close(conn);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

三.数据库连接池(优化数据库连接性能)

(一)连接池简介

为什么使用连接池?

    数据库连接是一种关键的有限的昂贵的资源,传统数据库连接每发出一个请求都要创建一个连接对象,使用完直接关闭不能重复利用;

传统连接的缺点:

    1.关闭资源需要手动完成,一旦忘记会造成内存溢出;

    2.请求过于频繁的时候,创建连接极其消耗内存;

    3.而且一旦高并发访问数据库,有可能会造成系统崩溃。

连接池原理

    数据库连接池负责分配、管理和释放数据库连接,它的核心思想就是连接复用,通过建立一个数据库连接池,这个池中有若干个连接对象,当用户想要连接数据库,就要先从连接池中获取连接对象,然后操作数据库。一旦连接池中的连接对象被用完了,判断连接对象的个数是否已达上限,如果没有可以再创建新的连接对象,如果已达上限,用户必须处于等待状态,等待其他用户释放连接对象,直到连接池中有被释放的连接对象了,这时候等待的用户才能获取连接对象,从而操作数据库。这样就可以使连接池中的连接得到高效、安全的复用,避免了数据库连接频繁创建、关闭的开销。这项技术明显提高对数据库操作的性能。

连接池的优势

         1)程序启动时提前创建好连接,不用用户请求时创建,给服务器减轻压力;

         2)连接关闭的时候不会直接销毁connection,这样能够重复利用;

         3)如果超过设定的连接数量但是还没有达到最大值,那么可以再创建;

         4)如果空闲了,会默认销毁(释放)一些连接,让系统性能达到最优;

常用的开源连接池

         1. DBCP

    Apache提供的数据库连接池,速度相对c3p0较快,但因自身存在BUGHibernate3已不再提供支持

         2. C3P0

           是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以。

         3.Druid

    是阿里提供的数据库连接池,据说是集DBCP C3P0 优点于一身的数据库连接池,但是速度不知道。

(二)c3p0连接池

  1. 下载jar包导入项目中

  1. 编写属性配置文件:c3p0.properties

注意事项:

  1. 属性配置文件的名称必须叫c3p0.properties,不能改文件名
  2. 该属性配置文件必须放在src路径目录下
  3. 属性配置文件中的属性名必须与上表中指定的名称相同,不能随意修改,而且必须加c3p0前缀。

选配:(了解)

c3p0.maxPoolSize = 100  最大连接数  默认15

c3p0.minPoolSize = 10   是小连接数 默认3

c3p0.initialPoolSize = 10  初始化连接数 在最大和最小之间

c3p0.maxIdleTime = 30   最大空闲时间,毫秒为单位

  1. 创建一个C3P0的工具类,获取数据源并返回连接对象。

package com.ujiuye.c3p0;

import com.mchange.v2.c3p0.ComboPooledDataSource;

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

/*c3p0连接池工具类*/
public class C3p0Utils {
    //获取连接的方法  DataSource
    public  static Connection getConn() throws SQLException {
        //创建数据源对象
        DataSource ds = new ComboPooledDataSource();
        //数据源对象调用getConnection()
        Connection connection = ds.getConnection();
        return  connection;
    }
}

 
  1. 测试查看   操作

package com.ujiuye.c3p0;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.ujiuye.bean.Admin;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

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

public class TestC3p0Utils {
    public static void main(String[] args) {
        String sql = "select * from admin";
        //创建QueryRunner使用c3p0连接池
        QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
        //QueryRunner runner1 = new QueryRunner();
        try {
            List<Admin> list = runner.query(sql, new BeanListHandler<Admin>(Admin.class));
            for (Admin admin : list) {
                System.out.println(admin);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

(三)Druid连接池

  1. 下载jar

                lib/druid-1.1.0.jar

  1. 编写druid.properties放在src目录下

  1. 创建工具类DruidUtils

package com.ujiuye.druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class DruidUtils {
    private  static DataSource ds = null;
    //获取数据源
    static {
        Properties properties = new Properties();
        try {
            //InputStream is  = new FileInputStream("D:\\savecode\\ideaPro\\changsha0308\\day10\\src\\druid.properties");
            InputStream is  = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            //调用load方法加载文件
            properties.load(is);
            //druid连接池中提供了createDataSource()方法获取数据源
            ds = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //获取数据源对象
    public  static  DataSource getDataSource(){
        return  ds;
    }

    //获取连接
    public  static Connection getConn(){
        try {
            return  ds.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return  null;
    }

}

 

  1. 测试

package com.ujiuye.druid;

import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;

import java.sql.Connection;
import java.sql.SQLException;

public class TestDruidUtils {
    @Test
    public void test01() {
        String sql = "delete from admin where id = ?";
        Connection conn = DruidUtils.getConn();
        QueryRunner runner = new QueryRunner();
        try {
            int row = runner.update(conn, sql, 24);
            System.out.println(row);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test02() {
        String sql = "delete from admin where id = ?";
        QueryRunner runner = new QueryRunner(DruidUtils.getDataSource());
        try {
            int row = runner.update(sql, 22);
            System.out.println(row);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

四.DAO

  • 什么是DAO

Data Access Object访问数据信息的类和接口,包括了对数据的CRUDCreateRetrivalUpdateDelete),而不包含任何业务相关的信息

三层:

表示层

业务逻辑层(最难)

数据访问层

  • 作用

为了实现功能的模块化,更有利于代码的维护和升级。

  • 封装
package com.ujiuye.dao;

  

  import com.mchange.v2.c3p0.ComboPooledDataSource;

  import org.apache.commons.dbutils.QueryRunner;

  import org.apache.commons.dbutils.handlers.BeanHandler;

  import org.apache.commons.dbutils.handlers.BeanListHandler;

  import org.apache.commons.dbutils.handlers.ScalarHandler;

  

  import java.sql.SQLException;

  import java.util.List;

  

  public class BaseDao<T> {

    QueryRunner runner = new QueryRunner(new ComboPooledDataSource());

  

    /*增删改*/

    public  int update(String sql,Object...params){

        int row = 0;

        try {

            row = runner.update(sql, params);

        } catch (SQLException e) {

            e.printStackTrace();

        }

        return  row;

    }

    /*查询集合*/

    public List<T> queryMulti(String sql,Class<T> clazz,Object...params){

        try {

            return runner.query(sql, new BeanListHandler<T>(clazz), params);

        } catch (SQLException e) {

            e.printStackTrace();

        }

        return  null;

    }

    /*查询单个值*/

    public T querySingle(String sql,Class<T> clazz,Object...params){

        try {

            return  runner.query(sql,new BeanHandler<T>(clazz),params);

        } catch (SQLException e) {

            e.printStackTrace();

        }

        return  null;

    }

  

    /*查询聚合函数,单行单列*/

    public  Object scale(String sql,Object...params){

        try {

            return  runner.query(sql,new ScalarHandler(),params);

        } catch (SQLException e) {

            e.printStackTrace();

        }

        return null;

    }

  

}
  • 使用
package com.ujiuye.dao;

  

  import com.mchange.v2.c3p0.ComboPooledDataSource;

  import com.ujiuye.entity.Admin;

  import org.apache.commons.dbutils.QueryRunner;

  import org.apache.commons.dbutils.handlers.BeanHandler;

  import org.apache.commons.dbutils.handlers.BeanListHandler;

  import org.apache.commons.dbutils.handlers.ScalarHandler;

  import org.junit.Test;

  

  import java.sql.SQLException;

  import java.util.List;

  

  public class AdminDao extends  BaseDao<Admin> {

    @Test

    public void insert_test(){

        String sql = "INSERT INTO admin(username,PASSWORD)VALUES(?,?)";

        int row = update(sql, "小刘", "333");

        System.out.println(row);

    }

  

    @Test

    public  void  select_multi(){

        String sql = "select  * from admin";

        List<Admin> list = queryMulti(sql, Admin.class);

        for (Admin admin : list) {

            System.out.println(admin);

        }

    }

  

    @Test

    public  void  select_single(){

        String sql = "select  * from admin where id = ?";

        Admin admin = querySingle(sql, Admin.class,1);

        System.out.println(admin);

    }

  

    @Test

    public  void  select_one(){

        String sql = "select  count(*) from admin";

        Object count = scale(sql);

        System.out.println(count);

    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值