泛型(三)模拟commons-dbutils

帅比萌擦擦* 提交于 2020-03-15 16:04:55

最近在复习泛型的知识,想起以前使用commons-dbutils的时候,觉得这个工具太厉害了。所以,试着自己瞎写看能不能模拟commons-dbutils的功能。

1、commons-dbutils的使用

  1.1、commons-dbutils是用来简化JDBC的代码。下面是其简单用法:

// 增删改
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());// 创建QueryRunner,需要提供数据库连接池对象
String sql = "insert into t_students values(?,?,?,?)";// 给出sql模板
Object[] params = { 1, "liSi", 20, "female" };// 给出sql模板的参数
qr.update(sql, params);

// 查询
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from t_student where id = ?";
Object[] params = {1};
Stu stu = qr.query(sql, new BeanHandler<Stu>(Stu.class), params);
// 将结果集rs映射成javabean,要求结果集列名与javabean属性名一致

  1.2、commons-dbutils的其他查询用法

* BeanListHandler的应用,它是多行处理器
    - QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
      String sql = "select * from t_stu";
      List<Stu> stuList = qr.query(sql,new BeanListHandler<Stu>(Stu.class));
* MapHandler的应用,它是单行处理器,把一行转换成一个Map对象
    - QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
      String sql = "select * from t_stu where sid = ?";
      Object[] params = {1001};
      Map map = qr.query(sql,new MapHandler(), params);
* MapListHandler,它是多行处理器,把每行都转换成一个Map
    - QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
      String sql = "select * from t_stu";
      List<Map<String,Object>> mapList = qr.query(sql, new MapListHandler());
* ScalarHandler的应用,它是单行单列时使用,最为合适
    - QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
      String sql = "select count(*) from t_stu";
      Object obj = qr.query(sql,new ScalarHandler());

 

2、模拟commons-dbutils

  2.1、工具类

  CommonUtils工具类的作用见我的博客:泛型的使用:封装工具类CommonUtils-把一个Map转换成指定类型的javabean对象(用到泛型)

package com.oy.type;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;

public class CommonUtils {

    // 把一个Map转换成指定类型的javabean对象
    public static <T> T tobean(Map<String, ?> map, Class<T> clazz) {
        try {
            T bean = clazz.newInstance();
            BeanUtils.populate(bean, map);
            return bean;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

 

  JdbcUtils类是用来获取数据库连接的,用到了c3p0连接池。

package com.oy.type;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class JdbcUtils {

    // 使用配置文件c3p0-config.xml, 放到src目录下
    private static ComboPooledDataSource dataSource = new ComboPooledDataSource();

    // 返回连接
    public static Connection getConnection(){
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 返回连接池对象
    public static DataSource getDataSource() {
        return dataSource;
    }
}

 

  c3p0-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config> 
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/db_test?useUnicode=true&amp;characterEncoding=UTF-8</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password"></property>
        <property name="acquireIncrement">3</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">2</property>
        <property name="maxPoolSize">10</property>
    </default-config>
    <named-config name="name1">
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/db_test</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">123</property>
        <property name="acquireIncrement">3</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">2</property>
        <property name="maxPoolSize">10</property>
    </named-config>
</c3p0-config>

 

  2.2、QR类

package com.oy.type;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;

public class QR<T> {
    private DataSource dataSource;

    public QR() {
        super();
    }

    public QR(DataSource dataSource) {
        super();
        this.dataSource = dataSource;
    }

    // 可以做增删改操作
    public int update(String sql, Object... params) {
        Connection con = null;
        PreparedStatement pstmt = null;
        try {
            con = dataSource.getConnection(); // 通过连接池得到连接对象
            pstmt = con.prepareStatement(sql);// 使用sql模板创建preparedStatement对象
            initParams(pstmt, params);// 对sql语句的?赋值
            return pstmt.executeUpdate(); // 执行
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally { // 释放资源
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (con != null) {
                    con.close();
                }
            } catch (SQLException e1) {
            }
        }
    }

    // 可以做查询操作
    public T query(String sql, BeanHandler<T> rh, Object... params) {
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = dataSource.getConnection(); // 通过连接池得到连接对象
            pstmt = con.prepareStatement(sql);// 使用sql模板创建preparedStatement对象
            initParams(pstmt, params);// 对sql语句的?赋值
            rs = pstmt.executeQuery(); // 执行查询,返回ResultSet对象

            return rh.handle(rs);// 传入结果集rs,得到T类型的对象
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pstmt != null) {
                    pstmt.close();
                }
                if (con != null) {
                    con.close();
                }
            } catch (SQLException e) {
            }
        }
    }

    public List<T> query(String sql, BeanListHandler<T> rh, Object... params) {
        Connection con = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            con = dataSource.getConnection(); // 通过连接池得到连接对象
            pstmt = con.prepareStatement(sql);// 使用sql模板创建preparedStatement对象
            initParams(pstmt, params);// 对sql语句的?赋值
            rs = pstmt.executeQuery(); // 执行查询,返回ResultSet对象

            return rh.handle(rs);// 传入结果集rs,得到T类型的对象
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pstmt != null) {
                    pstmt.close();
                }
                if (con != null) {
                    con.close();
                }
            } catch (SQLException e) {
            }
        }
    }

    // 给sql语句的?赋值
    private void initParams(PreparedStatement pstmt, Object... params) throws SQLException {
        if (params != null && params.length > 0) {
            for (int i = 0; i < params.length; i++) {
                pstmt.setObject(i + 1, params[i]);
            }
        }
    }
}

 

  2.3、BeanHandler:将查询的结果集转换成javabean

package com.oy.type;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
public class BeanHandler<T> {
    private Class<T> clazz;

    public BeanHandler(Class<T> clazz) {
        this.clazz = clazz;
    }

    public T handle(ResultSet rs) throws SQLException {
        if (!rs.next())
            return null;

        return CommonUtils.tobean(rsToMap(rs), clazz);
    }

    private Map<String, String> rsToMap(ResultSet rs) throws SQLException {
        Map<String, String> map = new HashMap<String, String>();
        int count = rs.getMetaData().getColumnCount(); // 获取结果集的列数
        for (int i = 1; i <= count; i++) { // 循环列
            String columnName = rs.getMetaData().getColumnName(i);// 获取列名
            String value = rs.getString(i); // 获取结果集一行中的每一列的值
            map.put(columnName, value);
        }
        return map;
    }
}

 

  2.4、BeanListHandler:将结果集转换成bean集合

package com.oy.type;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BeanListHandler<T> {
    private Class<T> clazz;

    public BeanListHandler(Class<T> clazz) {
        this.clazz = clazz;
    }

    public List<T> handle(ResultSet rs) throws SQLException {
        List<T> list = new ArrayList<>();
        Map<String, String> map = null;

        while (rs.next()) { // 循环行
            map = new HashMap<String, String>();
            int count = rs.getMetaData().getColumnCount(); // 获取结果集的列数
            for (int i = 1; i <= count; i++) { // 循环列
                String columnName = rs.getMetaData().getColumnName(i);// 获取列名
                String value = rs.getString(i); // 获取结果集一行中的每一列的值
                map.put(columnName, value);
            }
            list.add(CommonUtils.tobean(map, clazz));
        }

        return list;
    }
}

 

  2.5、MapHandler:将结果集转换成Map

package com.oy.type;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

public class MapHandler {

    public MapHandler() {}

    public Map<String, String> handle(ResultSet rs) throws SQLException {
        if (!rs.next())
            return null;
        return rsToMap(rs);
    }

    private Map<String, String> rsToMap(ResultSet rs) throws SQLException {
        Map<String, String> map = new HashMap<String, String>();
        int count = rs.getMetaData().getColumnCount(); // 获取结果集的列数
        for (int i = 1; i <= count; i++) { // 循环列
            String columnName = rs.getMetaData().getColumnName(i);// 获取列名
            String value = rs.getString(i); // 获取结果集一行中的每一列的值
            map.put(columnName, value);
        }
        return map;
    }
}

 

3、测试

package com.oy.type;
public class Stu {
    private Integer id;
    private Integer age;
    private String name;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Stu [id=" + id + ", age=" + age + ", name=" + name + "]";
    }
    
}
package com.oy.type;
import java.util.List;
import org.junit.jupiter.api.Test;

public class StuDao {
    QR<Stu> qr = new QR<>(JdbcUtils.getDataSource());
    
    public Stu getStuById(Integer id) {
        String sql = "select * from stu where id = ?";
        Object[] params = {id};
        return qr.query(sql, new BeanHandler<Stu>(Stu.class), params);
    }
    
    public List<Stu> getStus(String ids) {
        String sql = "select * from stu where id in (" + ids + ")";
        return qr.query(sql, new BeanListHandler<Stu>(Stu.class));
    }
    
    @Test
    public void test1() {
        //System.out.println(getStuById(1));
        System.out.println(getStus("1,2"));
    }
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!