JDBC之事务 批处理 BeanUtil的底层原理仿写

1、事务

几行代码一起执行,要么都成功,要么都失败,commit,rollback
    

 public class TestTransaction {
    @Test
    public void test(){
        //添加一个员工      
        Connection conn = DBUtilConnection.getThreadConnection();
        try {
              //开启事务
            conn.setAutoCommit(false);
            addEmp();
            System.out.println("员工添加成功");
            int num = 5/0;
            //添加一个部门
            addDept();
            System.out.println("部门添加成功");
            conn.commit();//提交事务
        } catch (Exception e) {
            //如果出异常,回滚
            try {
                conn.rollback();//回滚事务
                System.out.println("发生异常,数据回滚");
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }
​
    }
    public int addDept(){
        String sql = "insert into dept values(?,?,?)";
        Object[] params = {50,"武术部","武当山"};
        int i =  DBUtilConnection.executeUpdate(sql, params);
        return i;
    }
​
    public int addEmp(){
        Emp emp = null;
        try {
            emp = new Emp(1113,"张三丰","拳师",7902,new SimpleDateFormat("yyyy-MM-dd").parse("2022-2-2"),900.0,null,50);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        String sql = "insert into emp values(?,?,?,?,?,?,?,?)";
        Object[] params = {emp.getEmpno(),emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno()};
        int i = DBUtilConnection.executeUpdate(sql, params);
        return i;
    }
​
}
    
注意:事务跟连接相关,如果事务属于不同的连接,那么就无法回滚。
    你要控制事务,首先要搞明白是不是同一个连接。

2、批处理

批处理就是很多句sql一起处理
    
   1、不同类型的sql批处理
    public void test1() throws Exception {
        //测试批处理
         //不同类型的sql语句来一起处理---添加一个部门,删除一个部门
        Connection conn = DBUtilConnection.getThreadConnection();
        Statement stmt = conn.createStatement();
        String addSql = "insert into dept values(80,'测评部','成都')";
        String deleteSql = "delete from dept where deptno=60";
        //添加到批处理---装车
        stmt.addBatch(addSql);
        stmt.addBatch(deleteSql);
        int[] ints = stmt.executeBatch();
        System.out.println(Arrays.toString(ints));
​
    }
  2、相同类型大量数据的批处理--10008条部门---100条为一批去处理
     @Test
    //这个测试相同类型多条sql的批处理
    public void test() throws SQLException {
        Connection conn = DBUtilConnection.getThreadConnection();
        String sql = "insert into dept values(?,?,?)";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        //真正的生成批处理的sql
        for(int i=1;i<=10008;i++){
            pstmt.setInt(1,i);
            pstmt.setString(2,"部门"+i);
            pstmt.setString(3,"地址"+i);
            pstmt.addBatch();//加入到批处理
            if(i%100==0){
                int[] ints = pstmt.executeBatch();
                System.out.println(Arrays.toString(ints));
            }
        }
        //最后这模不尽的
        int[] ints = pstmt.executeBatch();
        System.out.println(Arrays.toString(ints));
​
    } 
      

3、BeanUtils组件的使用

<dependency>
      <groupId>commons-beanutils</groupId>
      <artifactId>commons-beanutils</artifactId>
      <version>1.9.3</version>
</dependency>
​
说白了,BeanUtils这个工具是简化对反射的操作的
    @Test
    public void test() throws  Exception {
        //BeanUtils是操作对象的,基于反射操作
        Dept dept = new Dept(10,"研发部","北京");
        //复制对象
       // Dept dept1 = (Dept)BeanUtils.cloneBean(dept);
      //  System.out.println(dept1==dept);
        //设置指定的属性
        //BeanUtils.setProperty(dept,"dname","开发部");
        //System.out.println(dept);
        //BeanUtils.copyProperty(dept,"dname","工程部");
        //System.out.println(dept);
        //复制所有的属性
        //Dept d2 = new Dept();
        //BeanUtils.copyProperties(d2,dept);
        //System.out.println(d2);
        //把所有的属性转换为Map集合
        Map<String, String> map = BeanUtils.describe(dept);
        map.remove("class");
        //System.out.println(map);
        //把集合转为对象
        Dept d1 = new Dept();
        map.put("deptno","100");
        BeanUtils.populate(d1,map);
        System.out.println(d1);
}

4、DBUtils组件使用

<dependency>
      <groupId>commons-dbutils</groupId>
      <artifactId>commons-dbutils</artifactId>
      <version>1.6</version>
</dependency>
​
public class TestDBUtils {
​
    @Test
    public void test() throws SQLException {
        QueryRunner runner = new QueryRunner();
        Object query = runner.query(DBUtilConnection.getThreadConnection(), "select count(*) from emp", new ScalarHandler<>());
        System.out.println(query);
    
    }
​
    @Test
    public void test3() throws SQLException {
        QueryRunner runner = new QueryRunner();
        String sql = "select ename,dname from emp join dept on emp.deptno=dept.deptno";
        List<Object[]> query = runner.query(DBUtilConnection.getThreadConnection(), sql, new ArrayListHandler());
        for(Object[] arr : query){
            System.out.println(Arrays.toString(arr));
        }
​
    }
​
    @Test
    public void test2() throws SQLException {
        QueryRunner runner = new QueryRunner();
        List<Emp> emps = runner.query(DBUtilConnection.getThreadConnection(), "select * from emp", new BeanListHandler<>(Emp.class));
        System.out.println(emps);
    }
​
    @Test
    public void test1() throws SQLException {
        QueryRunner runner = new QueryRunner();
        int res = runner.update(DBUtilConnection.getThreadConnection(), "delete from dept where deptno=1");
        System.out.println(res);
    }
​
}

5、DBUtils的仿写

DBUtils的总体思路是提供一个结果集的处理器,这个处理器去处理不同的结果集,得到不同的返回值。

5.1 编写处理器的父接口-MyResultSetHandler

public interface MyResultSetHandler<T> {
    T handle(ResultSet rs);//这个处理器的父接口规定了必须有一个处理结果集的方法
}

5.2 编写QueryRunner - MyQueryRunner

public class MyQueryRunner {
​
    //你给我构造一个数据源,我用这个连接池里面的连接---前提是没有事务
    private DataSource ds;
    public MyQueryRunner(DataSource ds){
        this.ds = ds;
    }
    //查询的方法
    public <T> T query(String sql,MyResultSetHandler<T> rsh,Object... params){
        Connection conn= null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            conn  = ds.getConnection();
            pstmt = conn.prepareStatement(sql);
            if(params!=null){
                for(int i=0;i<params.length;i++){
                    pstmt.setObject(i+1,params[i]);
                }
            }
            rs = pstmt.executeQuery();
            T t = rsh.handle(rs);
            return t;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            closeAll(rs,pstmt,conn);
        }
        return null;
    }
​
​
    //增删改的方法
    public int update(String sql,Object... params){
        int res = -1;
        Connection conn = null;
        PreparedStatement stmt = null;
        try {
            conn = ds.getConnection();
            stmt = conn.prepareStatement(sql);
            //设置参数
            if(params!=null){
                for(int i=0;i<params.length;i++){
                    stmt.setObject(i+1,params[i]);
                }
            }
            //执行sql
            res = stmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            closeAll(null,stmt,conn);
        }
        return res;
    }
​
    public  void closeAll(ResultSet rs, Statement stmt, Connection conn){
        try {
            if(rs!=null){
                rs.close();
                rs = null;//提醒垃圾回收
            }
            if(stmt!=null){
                stmt.close();
                stmt = null;//提醒垃圾回收
            }
            if(conn!=null){
                conn.close();
                conn = null;//提醒垃圾回收
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

5.3 编写处理器的子类

5.3.1 BeanListHandler
这个处理器把一个结果集处理成一个对象集合


public class MyBeanListHandler<T> implements MyResultSetHandler<List<T>> {
    Class<T> clazz;
    public MyBeanListHandler(Class<T> clazz){
        this.clazz = clazz;
    }
    @Override
    public List<T> handle(ResultSet rs) {
        //如何创建一个泛型对象---你只给我泛型是没法创建对象的,还必须给我这个类
        List<T> list = new ArrayList<>();
        try {
            while(rs.next()){
                T t = clazz.newInstance();
                int columnCount = rs.getMetaData().getColumnCount();
                for(int i=1;i<=columnCount;i++){
                    String columnName = rs.getMetaData().getColumnName(i);
                    Object value = rs.getObject(columnName);
                    BeanUtils.setProperty(t,columnName,value);
                }
                list.add(t);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return list;
    }
}
​

5.3.2 MyArrayListHandler


public class MyArrayListHandler implements MyResultSetHandler<List<Object[]>>{
    @Override
    public List<Object[]> handle(ResultSet rs) {
        List<Object[]> list = new ArrayList<>();
        //把结果集处理成这么一个数组就可以了
        try {
            //查询列的数量就是我数组的长度
            int columnCount = rs.getMetaData().getColumnCount();
            while(rs.next()){
                Object[] row = new Object[columnCount];
                for(int i=0;i<row.length;i++){
                    row[i] = rs.getObject(i+1);
                }
                list.add(row);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }
}

5.3.3 查询第一行第一列


public void test() throws SQLException {
        Object res = runner.query("select ename from emp where empno=7369", new MyResultSetHandler<Object>() {
            public Object handle(ResultSet rs) {
                try {
                    if (rs.next()) {
                        return rs.getObject(1);
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return null;
            }
        });
        System.out.println(res);
}

5.4 编写工具类

public class MyDBUtil {
    private static String driver = "";
    private static String url = "";
    private static String username = "";
    private static String password = "";
    private static DruidDataSource ds = new DruidDataSource();
​
    static {
        Properties prop = new Properties();
        InputStream is = MyDBUtil.class.getClassLoader().getResourceAsStream("db.properties");
        try {
            prop.load(is);
            driver = prop.getProperty("jdbc.driver");
            url = prop.getProperty("jdbc.url");
            username = prop.getProperty("jdbc.username");
            password = prop.getProperty("jdbc.password");
            ds.setDriverClassName(driver);
            ds.setUrl(url);
            ds.setUsername(username);
            ds.setPassword(password);
            ds.setMaxActive(100);//最大活动数量100个
            ds.setInitialSize(20);
            ds.setMinIdle(20);
            ds.setMaxWait(1000*60);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    //封装一个获取MyRunner的方法
    public static MyQueryRunner getRunner(){
        return new MyQueryRunner(ds);
    }
}
​
​
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值