尚硅谷之JDBC

117 篇文章 0 订阅
116 篇文章 0 订阅

1.4 抽取BasicDAO

package com.atguigu.dao.impl;

 

/*

 * 这个类的作用是:对DAOImpl再次抽象,把共同的部分再次抽取

 */

import java.lang.reflect.Field;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

 

import com.atguigu.utils.JDBCUtils;

 

//泛型类

public abstract class BasicDAOImpl<T> {

    private Class<T> type;

 

    @SuppressWarnings("all")

    protected BasicDAOImpl() {

        // 为什么要在构造器中写,因为子类继承BasicDAOImpl类一定会调用父类的构造器

        Class clazz = this.getClass();// this代表的是正在创建的那个对象,即子类的对象

 

        // 获取clazz的带泛型父类信息

        Type superType = clazz.getGenericSuperclass();

 

        // Father<String>:参数化的类型

        ParameterizedType p = (ParameterizedType) superType;

 

        // 获取泛型实参

        Type[] ts = p.getActualTypeArguments();

 

        // 因为当前类只有一个泛型形参,即子类中只有一个泛型实参

        type = (Class) ts[0];

    }

 

    protected int update(String sql, Object... params) throws SQLException {

        //1、获取连接

        Connection conn = JDBCUtils.getConnection();

        //2、执行更新数据库语句

        int len = executeUpdate(conn, sql, params);

        //3、关闭连接

        JDBCUtils.closeQuietly(conn);

        return len;

    }

 

    // 如果有需要在一个事务中完成更新,可以调用这个带conn的方法

    protected int update(Connection conn, String sql, Object... params) throws SQLException {

        //执行更新数据库语句

        int len = executeUpdate(conn, sql, params);

        return len;

    }

 

    private int executeUpdate(Connection conn, String sql, Object... params) throws SQLException {

        //1sql预编译

        PreparedStatement pst = conn.prepareStatement(sql);

 

        //2、设置sql中的?

        if (params != null && params.length > 0) {

            // 数组的下标是从0开始,?的编号是1开始

            for (int i = 0; i < params.length; i++) {

                pst.setObject(i + 1, params[i]);

            }

        }

 

        //3、执行sql

        int len = pst.executeUpdate();

       

        //4、释放资源

        JDBCUtils.closeQuietly(pst);

        return len;

    }

 

    //通用的查询方法之一:查询一行,即一个对象

    /**

     * 执行查询操作的SQL语句,SQL可以带参数(?)

     * @param sql String 执行查询操作的SQL语句

     * @param args Object... 对应的每个?设置的值,顺序要与?对应

     * @return T 封装了查询结果的实体

     * @throws Exception

     */

    protected T get(String sql, Object... params) throws Exception {

        //1、获取连接

        Connection conn = JDBCUtils.getConnection();

       

        //2、执行查询语句

        ResultSet rs = executeQuery( conn,sql, params);

 

        //3、处理查询结果

        //(1)获取查询的结果集的元数据信息

        ResultSetMetaData rsmd = rs.getMetaData();

       

        //(2)这是查询的结果集中,一共有几列

        int count = rsmd.getColumnCount();

 

        //(3)创建实例对象

        T t = type.newInstance();// 要求这个Javabean类型必须有无参构造

 

        //(4)遍历结果集

        while (rs.next()) {

            /*

             * 问题? (1)sql语句中查询了几列,每一列是什么属性 (2)怎么把这个值设置到Javabean的属性中

             */

            // (5)循环每一行有几列

            for (int i = 0; i < count; i++) {

                // (6)获取第几列的名称

                // String columnName = rsmd.getColumnName(i+1);

                // 如果sql中没有取别名,那么就是列名,如果有别名,返回的是别名

                String fieldName = rsmd.getColumnLabel(i + 1);

 

                // (7)获取该列的值

                // Object value = rs.getObject(columnName);

                Object value = rs.getObject(fieldName);

 

                // (8)设置obj对象的某个属性中

                Field field = type.getDeclaredField(fieldName);// JavaBean的属性名

                field.setAccessible(true);

                field.set(t, value);

            }

        }

 

        //4、释放资源

        JDBCUtils.closeQuietly(rs);

        JDBCUtils.closeQuietly(conn);

       

        return t;

    }

 

    private static ResultSet executeQuery(Connection conn, String sql,  Object... params) throws SQLException {

        //1sql预编译

        PreparedStatement pst = conn.prepareStatement(sql);

 

        //2、设置?

        if (params != null && params.length > 0) {

            // 数组的下标是从0开始,?的编号是1开始

            for (int i = 0; i < params.length; i++) {

                pst.setObject(i + 1, params[i]);

            }

        }

 

        //3、查询

        ResultSet rs = pst.executeQuery();

        return rs;

    }

 

    // 通用的查询方法之二:查询多行,即多个对象

    // Class<T> clazz:用来创建实例对象,获取对象的属性,并设置属性值

    /**

     * 执行查询操作的SQL语句,SQL可以带参数(?)

     * @param sql String 执行查询操作的SQL语句

     * @param args Object... 对应的每个?设置的值,顺序要与?对应

     * @return ArrayList<T> 封装了查询结果的集合

     * @throws Exception

     */

    public ArrayList<T> getList(String sql, Object... args) throws Exception {

        // 1、获取连接

        Connection conn = JDBCUtils.getConnection();

 

        //2、执行查询sql

        ResultSet rs = executeQuery(conn,sql, args);

       

        //3、获取结果集的元数据

        ResultSetMetaData metaData = rs.getMetaData();

        // 获取结果中总列数

        int count = metaData.getColumnCount();

 

        // 创建集合对象

        ArrayList<T> list = new ArrayList<T>();

 

        while (rs.next()) {// 遍历的行

            // 1、每一行是一个对象

            T obj = type.newInstance();

 

            // 2、每一行有很多列

            // for的作用是为obj对象的每一个属性设置值

            for (int i = 0; i < count; i++) {

                // (1)每一列的名称

                String fieldName = metaData.getColumnLabel(i + 1);// 获取第几列的名称,如果有别名获取别名,如果没有别名获取列名

                // (2)每一列的值

                Object value = rs.getObject(i + 1);// 获取第几列的值

                // (3)获取属性对象

                Field field = type.getDeclaredField(fieldName);

                // (4)设置可见性

                field.setAccessible(true);

                // (5)设置属性值

                field.set(obj, value);

            }

 

            // 3、把obj对象放到集合中

            list.add(obj);

        }

 

        // 6、释放资源

        JDBCUtils.closeQuietly(rs);

        JDBCUtils.closeQuietly(conn);

 

        // 7、返回结果

        return list;

    }

   

    //通用的查询方法之三:查询单个值

    //单值:select max(salary) from employee;   一行一列

    //select count(*) from t_goods; 一共几件商品

    public Object getValue(String sql,Object... args)throws Exception{

        //1、获取连接

        Connection conn = JDBCUtils.getConnection();

       

        //2、执行查询sql

        ResultSet rs = executeQuery(conn, sql, args);

       

        Object value = null;

        if(rs.next()){//一行

            value = rs.getObject(1);//一列

        }

       

        //3、释放资源

        JDBCUtils.closeQuietly(rs);

        JDBCUtils.closeQuietly(conn);

       

        return value;

    }

 

    //通用的查询方法之四:查询多行多列,但每一行又不是一个JavaBean

    /*

     * SELECT did,AVG(salary),MAX(Salary) FROM t_employee GROUP BY did;

     * did  avg(salary)  max(salary)

        1   1990.90     8900

        2   4889    6899

     */

    public List<Map<String,Object>> getListMap(String sql,Object... args)throws Exception{

        //1、获取连接

        Connection conn = JDBCUtils.getConnection();

       

        //2、执行sql

        ResultSet rs = executeQuery(conn, sql, args);

       

        //获取结果集的元数据对象

        ResultSetMetaData metaData = rs.getMetaData();

        //一共有几列

        int count = metaData.getColumnCount();

        //创建List

        ArrayList<Map<String,Object>> list = new ArrayList<Map<String,Object>>();

         

        while(rs.next()){

            //每一行是一个Map的对象

            HashMap<String,Object> map = new HashMap<String,Object>();

           

            //map的key是列名

            for (int i = 0; i < count; i++) {

                //(1)获取列名或别名

                String columnName = metaData.getColumnLabel(i+1);

                //(2)获取对应的值

                Object value = rs.getObject(i+1);

                //(3)把这对值放到map中

                map.put(columnName, value);

            }

           

            //把map放到List中

            list.add(map);

        }

       

        //6、释放资源

        JDBCUtils.closeQuietly(rs);

        JDBCUtils.closeQuietly(conn);

       

        return list;

    }

 

    //通用的查询方法之四:查询一行多列,但一行又不是一个JavaBean

    public Map<String,Object> getMap(String sql,Object... args)throws Exception{

        List<Map<String, Object>> listMap = getListMap(sql,args);

        if(listMap.size()>0){

            return listMap.get(0);

        }

        return null;

    }

}

 

 

 

 

本教程由尚硅谷教育大数据研究院出品,如需转载请注明来源。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值