JDBC-Apache的commons-DButils(最实用数据库工具类库)

问题引出

显然这也是一个JDBC工具类-这个是一个类库,包含多个类
这个工具类库中的类不同于之前的工具类
问题
1.之前的工具类有一个问题-就是当我们的connection关闭之后
如果我们调用的是查询返回resultSet那么这个resultSet也会被关闭(无法再获取数据)
就无法调用
我们需要保证得到数据再快速释放连接来保证效率
这两者是冲突的,所以就出现了这个工具类
2.resultSet不利于数据管理(只能用一次)-就算你用完后再释放连接,可能后面也需要这些数据,但是resultSet也关闭了,就不能再次调用数据
3.就是我们只能通过getInt/String…(位置/“列名”)获取相应数据
不直观,还要自己判断类型,更希望通过方法名直观体现-getName()这种
在这里插入图片描述
解决方法
1.创建一个和我们表相对的简单类(列名-变量名和数据类型相对应)
2.想办法我们我们结果集取得的数据一个个赋值给对象,然后把我们的actor对象存储到ArrayList中,就得到了对应数据

土办法代码封装

这里就根据我们之前的推论自己实现一下
先写一个简单的actor类-需要无参和有参构造器,所有属性的get和set

import java.util.Date;

/**
 * Actor 对象和 actor表的记录对应
 *
 */
public class Actor { //Javabean, POJO, Domain对象

    private Integer id;
    private String name;
    private String sex;
    private Date borndate;
    private String phone;

    public Actor() { //一定要给一个无参构造器[反射需要]
    }

    public Actor(Integer id, String name, String sex, Date borndate, String phone) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.borndate = borndate;
        this.phone = phone;
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBorndate() {
        return borndate;
    }

    public void setBorndate(Date borndate) {
        this.borndate = borndate;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "\nActor{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", borndate=" + borndate +
                ", phone='" + phone + '\'' +
                '}';
    }
}

主程序代码

 @Test
    public ArrayList<Actor> testSelectToArrayList() {

        System.out.println("使用 druid方式完成");
        //1. 得到连接
        Connection connection = null;
        //2. 组织一个sql
        String sql = "select * from actor where id >= ?";
        PreparedStatement preparedStatement = null;
        ResultSet set = null;
        ArrayList<Actor> list = new ArrayList<>();//创建ArrayList对象,存放actor对象
        //3. 创建PreparedStatement 对象
        try {
            connection = JDBCUtilsByDruid.getConnection();
            System.out.println(connection.getClass());//运行类型 com.alibaba.druid.pool.DruidPooledConnection
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, 1);//给?号赋值
            //执行, 得到结果集
            set = preparedStatement.executeQuery();

            //遍历该结果集
            while (set.next()) {
                int id = set.getInt("id");
                String name = set.getString("name");//getName()
                String sex = set.getString("sex");//getSex()
                Date borndate = set.getDate("borndate");
                String phone = set.getString("phone");
                //把得到的resultset 的记录,封装到 Actor对象
                //放入到list集合!!!
                list.add(new Actor(id, name, sex, borndate, phone));
            }

            System.out.println("list集合数据=" + list);
            for(Actor actor : list) {
                System.out.println("id=" + actor.getId() + "\t" + actor.getName());
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            JDBCUtilsByDruid.close(set, preparedStatement, connection);
        }
        //因为ArrayList 和 connection 没有任何关联,所以该集合可以复用.
        return  list;
    }

匹配sql和JavaBean(创建的类)属性之间的匹配问题

在这里插入图片描述
简单来说
int,double等基本数据类型在java对应数据类型的包装类(比如sql的int对应Java的Integer)
sql的日期形-java.utils.Date
sql的varchar,char-java的String

简介

在这里插入图片描述

常用的工具类
1.QueryRunner类-封装sql运行实现CRUD以及批处理
2.ResultSetHandler接口-处理ResultSet
在这里插入图片描述
这些是实现了ResultHandler的一些类
这里的JavaBean相当于我们之前创建的简单类

代码

首先!还是要导入jar包的!就之前那样

package yuan.hsp.JDBC.jdbcutils;

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

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

import yuan.hsp.JDBC.conchi.druidutils;

//用commons-dbutils也是目前最高效的工具类库-需要导入jar包
public class ThelasApacheutils {
	public static void main(String[] args) throws Exception {
		//1.得到连接(druid)
		Connection connection = druidutils.getConnection();
		//2.引入相应jar包
		//3.创建QueryRunner
		QueryRunner queryRunner = new QueryRunner();
		//4.执行相关的方法返回ArrayList结果集
		String sql="select * from actor where id >= ?";
		//解释:
		//query方法就是1.执行sql语句,得到result---封装到--》ArrayList集合中,然后返回集合
		//2.sql语句就是我们需要执行的语句
		//3.需要先得到connection连接
		//4.new BeanListHandler<>(Actor.class):在将resultSet->Actor对象-》封装到ArrayList对象中
		//传class对象看具体的数据结构-决定sql哪个参数传给java类哪个参数,底层用反射机制
		//5.最后的参数1,是传给我们sql语句的?的,有多个问号就写多个,按照顺序,写到最后
		//6.底层得到的resultset会在query关闭,还有底层创建的prepareStatement也会关闭,我们只需要释放连接即可
		List<Actor> query = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);
		System.out.println("输出集合信息");
		for (Actor q : query) {
			System.out.println(q);
		}
		//5.释放资源
		druidutils.close(null, null, connection);
	}
}

在这里插入图片描述
query这个方法逆天的
底层等会我们细究
不仅帮我们自动匹配属性和sql的列
还帮我们把resultSet的属性按照我们创建的
ResultHanddler下的类按照对应形式来存储到对应的List对象中
返回,而且帮我们自动关闭了ResultSet和prepareStatement
我们需要写简单类,获取连接,写sql语句,关闭连接
其他全可以让这个工具类完成

源码分析

new BeanListHandler<>(Actor.class)
这里就和Actor已经绑定了

分析 queryRunner.query方法:
          public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
                 PreparedStatement stmt = null;//定义PreparedStatement
                 ResultSet rs = null;//接收返回的 ResultSet
                 Object result = null;//返回ArrayList
        
             try {
                  stmt = this.prepareStatement(conn, sql);
                     //创建PreparedStatement
                  this.fillStatement(stmt, params);
                     //对sql 进行 ? 赋值,params就是我们对应参数
                  rs = this.wrap(stmt.executeQuery());
                     //执行sql,返回resultset
          result = rsh.handle(rs);//rsh是ResultSetHandler那个,返回集合
//返回的resultset --> arrayList[result] [使用到反射,对传入class对象处理]
                 } catch (SQLException var33) {
                     this.rethrow(var33, sql, params);//异常处理
                 } finally {
                     try {
                        this.close(rs);//关闭resultset
                    } finally {
                        this.close((Statement)stmt);//关闭preparedstatement对象
                     }
                  }
         
                return result;
             }
         

ResultSetHandler实现类(查询操作)

在这里插入图片描述
我们创建的这种类决定,query返回的数据和数据类型-到底是每一行,还是第一行,还是某一列

比如现在我们想查询一行数据只用一个对象接收即可

@Test
	public void tset_cha2() throws SQLException {
		//1.获取连接
		Connection connection = druidutils.getConnection();
		//2.创建QueryRunner对象,组织sql语句
		QueryRunner queryRunner = new QueryRunner();
		String sql="select * from actor where id = ?";
		//3.看SQL语句要返回单个,这里用我们创建的对象接收的话,对应的ResultSetHandler的实现类为BeanHandler
		Actor query = queryRunner.query(connection, sql, new BeanHandler<>(Actor.class), 1);
		System.out.println(query.getName()+query.getPhone()+query.getSex());
		//4.释放资源
		druidutils.close(null, null, connection);
	}

在这里插入图片描述

单列单行

这里用的是上图没写的,步骤其实都差不多
ScalarHandler
在这里插入图片描述
控制台输出
在这里插入图片描述

Apache-DML操作

挺简单的
接收换个方法从query变为update

@Test
	public void tset_DML() throws SQLException {
		//1.获取连接 
		Connection connection = druidutils.getConnection();
		//2.创建QueryRunner对象,组织sql语句
		QueryRunner queryRunner = new QueryRunner();
		String sql="update actor set name = ? where id = ?";
		//3.update执行dml语句
		int update = queryRunner.update(connection, sql, "郭靖", 4);
		//返回的是受影响的行数
		System.out.println("受影响的行数位"+update);
		//4.释放资源
		druidutils.close(null, null, connection);
	}

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小袁拒绝摆烂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值