Java 杂谈每日一篇Java程序员技术栈

JDBC基础(二)-封装DDL\DML\DQL工具类

2018-08-14  本文已影响40人  sixleaves

1. 封装DDL\DML\DQL工具类

1.1 为什么要自己抽取工具类,不用现成的

1.2 封装DML和DDL工具方法

我们首先要思考如何封装DML和DDL工具方法。DML指常用的数据库的增删改、DDL主要指建表改表语句.

这两个类操作可以封装成一个方法,我们定义这个方法叫update

update方法的设计

public class CommonUtil {

    public static int update(String sql, Object...values) throws SQLException {
        Connection conn = null;
        PreparedStatement ps = null;
        int rows = -1;
        try {
            conn = JDBCUtil.getConn();

            ps = conn.prepareStatement(sql);
            int len = values.length;
            for (int i = 0; i <len; i++) {
                ps.setObject(i+1, values[i]);
            }
            rows = ps.executeUpdate();
        } finally {
            JDBCUtil.close(conn, ps);
            return rows;
        }
    }
}

1.3 封装通用查询方法

DML和DDL的方法封装很简单。较为复杂的就是DQL方法的封装.因为对于DQL我们需要处理查询后返回的数据, 而这些数据如何处理对于不同的实体对象又不一样。我会分享如何一步步的抽取通用的查询方法。

什么是ORM

ORMObject Relation Mapping的缩写.在Web开发中其意思就是将数据库查询数据, 转换成程序中的对象的过程.做ORM的框架有很多, 比如Hibernate, Mybatis.

query方法的设计

先给方法取给通俗移动的方法名, 既然是查询,就叫query.

1.3.1 ORM版本一,根据列索引获取数据

先使用列索引, 在关于数据库的操作中, 索引都是从1开始计数.

    @Test
    public void testResultTest1() {

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        String sql = "select id, name, age, gender, birthday from t_customer";
        List<Customer> customers = new ArrayList<>();
        try {
            conn = JDBCUtil.getConn();
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();

            while (rs.next()) {
                int id = rs.getInt(1);
                String name = rs.getString(2);
                int age = rs.getInt(3);
                String gender = rs.getString(4);
                Date birthday = rs.getDate(5);
                customers.add(new Customer(id, name, age, gender,birthday));
            }

        }  catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, ps, rs);
        }


        for (Customer c : customers) {
            System.out.println(c);
        }
    }

1.3.2 ORM版本二,根据标签获取虚表数据

由于使用列索引的方式, 是一种硬编码.只要当前查询语句的列一变,那么代码也得改.所以基于这种考虑。我们进行重构,改成基于虚表中的列名.结果集对象的getXxx(String)这个接口接受的就是虚表的列名而不是, 对于有别名的使用的是别名.

    @Test
    public void testResultTest2() {

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        String sql = "select id, name, age, gender, birthday birth from t_customer";
        List<Customer> customers = new ArrayList<>();
        try {
            conn = JDBCUtil.getConn();
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();

            while (rs.next()) {
                // 使用虚表的列名
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                String gender = rs.getString("gender");
                Date birthday = rs.getDate("birth");
                customers.add(new Customer(id, name, age, gender,birthday));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, ps, rs);
        }

        for (Customer c : customers) {
            System.out.println(c);
        }
    }

1.3.3 ORM版本三,根据表元数据属性对象创建.

在1.3.2 的这个版本中, 我们需要需要手动的指定列的名称.但是有一部分信息我们没有利用。

1.3.2 存在的问题

下面的代码用到了反射技术.主要步骤如下

    @Test
    public void testResultTest3_metadata() {

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        String sql = "select id, name, age, gender, birthday birth from t_customer";
        List<Customer> customers = new ArrayList<>();
        try {
            conn = JDBCUtil.getConn();
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            ResultSetMetaData rsmd = ps.getMetaData();

            // 获取列的总个数
            int rolCount = rsmd.getColumnCount();

            // 获取原始列表的列名,这个列名不是虚表名
            for (int i = 0; i < rolCount; i++) {
//                System.out.print(rsmd.getColumnName(i+1) + "\t");
            }

//            System.out.println();
            // 获取虚表的列名, 使用列标签
            ArrayList<String> colLabels = new ArrayList<>();
            for (int i = 0; i < rolCount; i++) {
                colLabels.add(rsmd.getColumnLabel(i+1));
            }
            while (rs.next()) {
                // 使用虚表的列名
                // 元数据 ---- 描述数据的数据称为元数据.获取表的描述数据
                for (int i = 0; i < rolCount; i++) {

                   Object value = rs.getObject(colLabels.get(i));
                   System.out.print(value + "\t");
                }
                System.out.println();
            }

        }  catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(conn, ps, rs);
        }

        for (Customer c : customers) {
            System.out.println(c);
        }
    }

1.3.4 ORM版本四,根据反射泛型封装通用查询版本

1.3.3 版本的问题

    public static <T> List<T> query(Class<T> clazz, String sql, Object...values)
            throws IllegalAccessException, SQLException, NoSuchFieldException,
            InstantiationException, ClassNotFoundException {

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<T> beans = new ArrayList<T>();
        try {
            conn = JDBCUtil.getConn();
            ps = conn.prepareStatement(sql);

            int valuesCount = values.length;
            for (int i = 0; i < valuesCount; i++) {
                ps.setObject(i+1, values[i]);
            }

            rs = ps.executeQuery();
            ResultSetMetaData rsmd = ps.getMetaData();

            // 获取列的总个数
            int rolCount = rsmd.getColumnCount();

            while (rs.next()) {

                T bean = clazz.newInstance();

                // 使用虚表的列名
                // 元数据 ---- 描述数据的数据称为元数据.获取表的描述数据
                for (int i = 0; i < rolCount; i++) {

                    String label = rsmd.getColumnLabel(i+1);
                    Field field = Customer.class.getDeclaredField(label);
                    field.setAccessible(true);
                    Object value = rs.getObject(label);
                    field.set(bean, value);
                }
                beans.add(bean);
            }
        }  finally {
            JDBCUtil.close(conn, ps, rs);
        }
        return beans;
    }

最终封装好的CommonUtils.


public class CommonUtil {

    public static int update(String sql, Object...values) throws SQLException {
        Connection conn = null;
        PreparedStatement ps = null;
        int rows = -1;
        try {
            conn = JDBCUtil.getConn();

            ps = conn.prepareStatement(sql);
            int len = values.length;
            for (int i = 0; i <len; i++) {
                ps.setObject(i+1, values[i]);
            }
            rows = ps.executeUpdate();
        } finally {
            JDBCUtil.close(conn, ps);
            return rows;
        }
    }

    public static <T> List<T> query(Class<T> clazz, String sql, Object...values)
            throws IllegalAccessException, SQLException, NoSuchFieldException,
            InstantiationException, ClassNotFoundException {

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        List<T> beans = new ArrayList<T>();
        try {
            conn = JDBCUtil.getConn();
            ps = conn.prepareStatement(sql);

            int valuesCount = values.length;
            for (int i = 0; i < valuesCount; i++) {
                ps.setObject(i+1, values[i]);
            }

            rs = ps.executeQuery();
            ResultSetMetaData rsmd = ps.getMetaData();

            // 获取列的总个数
            int rolCount = rsmd.getColumnCount();

            while (rs.next()) {

                T bean = clazz.newInstance();

                // 使用虚表的列名
                // 元数据 ---- 描述数据的数据称为元数据.获取表的描述数据
                for (int i = 0; i < rolCount; i++) {

                    String label = rsmd.getColumnLabel(i+1);
                    Field field = Customer.class.getDeclaredField(label);
                    field.setAccessible(true);
                    Object value = rs.getObject(label);
                    field.set(bean, value);
                }
                beans.add(bean);
            }
        }  finally {
            JDBCUtil.close(conn, ps, rs);
        }
        return beans;
    }
}

后续

请继续关注JDBC基础(三).下篇我将分享的是

上一篇 下一篇

猜你喜欢

热点阅读