BaseDAO的抽取

BaseDAO介绍:

DAO:Data Access Object 数据访问对象

将访问数据库的操作封装起来。

若一个应用程序需要多个DAO,如订单的DAO,顾客的DAO,商品的DAO

可能发现自己对每个DAO重复基本上相同的创建、读取、更新和删除代码

因此有必要再抽象出一个基类BaseDAO,封装这些重复性的代码

BaseDAO抽取:

public abstract class BaseDAO<T> {
    private static String url;
    private static String username;
    private static String pwd;
    private static String driver;

    // entityClass用于接收子类继承时传进来的泛型
    private Class entityClass;

    private PreparedStatement pstmt = null;
    private Connection conn = null;
    private ResultSet rst = null;
}

0x01 驱动注册

// 静态代码块在类加载的时候会执行
// 让驱动注册在类加载时执行
// 从jdbc.properties文件(放在src文件夹下)中获取属性
static {
    try {
        // 1.创建Properties集合类
        Properties pro = new Properties();
        // 2.加载文件
        // 获取src路径下的文件的方法: ClassLoader 类加载器  ①加载字节码文件进内存;②获取src下资源文件的路径
        ClassLoader classLoader = BaseDAO.class.getClassLoader();
        URL re = classLoader.getResource("jdbc.properties");
        String path = null;
        if (re != null) {
            path = re.getPath();
        }
        if (path != null) {
            pro.load(new FileReader(path));
        }
        // 3.获取属性
        url = pro.getProperty("url");
        username = pro.getProperty("username");
        pwd = pro.getProperty("pwd");
        driver = pro.getProperty("driver");
        System.out.println(url);
        System.out.println(username);
        // 4.加载驱动
        Class.forName(driver);
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}

0x02 获取数据库连接对象

public static Connection getConn() {
    try {
        return DriverManager.getConnection(url,username,pwd);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return null;
}

0x03 释放资源

private void close(ResultSet rs, PreparedStatement psmt, Connection conn) {
    try {
        if (rs != null) {
            rs.close();
        }
        if (psmt != null) {
            psmt.close();
        }
        if (conn != null && !conn.isClosed()) {
            conn.close();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

0x04 泛型获取

public BaseDAO() {
    // BaseDAO的子类会默认调用父类的无参构造器
    // 即这边调用getClass()的为BaseDAO的子类(其他层的DAO)
    // getGenericSuperclass()获得带有泛型的父类
    // Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
    Type genericType = getClass().getGenericSuperclass();
    // ParameterizedType参数化类型,即泛型
    // getActualTypeArguments获取参数化类型的数组,泛型可能有多个
    // 如  class Child extends Father<Integer, String, Float>
    //     class Father<T1,T2,T3>
    //     此时这边的actualTypeArguments为 [Integer, String, Float]
    Type[] actualTypeArguments = ((ParameterizedType)genericType).getActualTypeArguments();
    Type actualType = actualTypeArguments[0];
    try {
        entityClass = Class.forName(actualType.getTypeName());
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

0x05 设置参数

由于查询和更新的操作均需要设置参数,此处抽取出一个方法

private void setParams(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]);
        }
}

0x06 更新

public int executeUpdate(String sql, Object... params) {
    try {
        conn = getConn();
        if (conn != null) {
            pstmt = conn.prepareStatement(sql);
        }
        setParams(pstmt, params);
        return pstmt.executeUpdate();
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(null, pstmt, conn);
    }
    return 0;
}

0x07 查询

查询得到的结果集,我们需要存储到一个列表并返回

但我们并不知道具体的列表元素的类型是什么,因此通过反射的技术给对象赋值

private void setValue(Object obj, String property, Object propertyValue) {
    // 获取obj的类
    Class clazz = obj.getClass();
    try {
        // 获取obj类的”property“成员字段
        Field field = clazz.getDeclaredField(property);
        // 设置访问权限为可访问
        field.setAccessible(true);
        // 给成员字段赋值propertyValue
        field.set(obj, propertyValue);
    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }
}

查询多行:

public List<T> executeQuery(String sql, Object...params) {
    try {
        conn = getConn();
        pstmt = conn.prepareStatement(sql);
        setParams(pstmt, params);
        rst = pstmt.executeQuery();

        // 获取结果集的元数据,即字段名、列数、字段类型等...
        ResultSetMetaData rsmd = rst.getMetaData();
        // 获取列数
        int columnCount = rsmd.getColumnCount();
        List<T> list = new ArrayList<>();
        T entity = (T) entityClass.getDeclaredConstructor().newInstance();
        while(rst.next()) {
            // 循环每一列,赋值给entity的成员变量
            // 注:entity的成员变量名需和结果集的列名对应相同
            for (int i = 0; i < columnCount; i++) {
                String columnName = rsmd.getColumnName(i+1);
                Object columnValue = rst.getObject(i+1);
                setValue(entity, columnName, columnValue);
            }
            list.add(entity);
        }
        return list;
    } catch (SQLException | IllegalAccessException | NoSuchMethodException | InstantiationException | InvocationTargetException e) {
        e.printStackTrace();
    } finally {
        close(rst, pstmt, conn);
    }
    return null;
}

查询单行:和多行类似

public T load(String sql, Object...params) {
    try {
        conn = getConn();
        pstmt = conn.prepareStatement(sql);
        rst = pstmt.executeQuery();
        ResultSetMetaData rsmd = rst.getMetaData();
        int count = rsmd.getColumnCount();
        T entity = (T) entityClass.getDeclaredConstructor().newInstance();
        if(rst.next()) {
            for (int i = 0; i < count; i++) {
                String columnName = rsmd.getColumnName(i+1);
                Object columnValue = rst.getObject(i+1);
                setValue(entity, columnName, columnValue);
            }
        }
        return entity;
    } catch (SQLException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
        e.printStackTrace();
    } finally {
        close(rst, pstmt, conn);
    }
    return null;
}

复杂查询:如统计总记录数 select count(*) from table_name

public Object[] executeComplex(String sql, Object...params) {
    try {
        conn = getConn();
        pstmt = conn.prepareStatement(sql);
        setParams(pstmt, params);
        rst = pstmt.executeQuery();

        ResultSetMetaData rsmd = rst.getMetaData();
        int columnCount = rsmd.getColumnCount();
        Object[] columnValueArr = new Object[columnCount];
        while(rst.next()) {
            for (int i = 0; i < columnCount; i++) {
                Object columnValue = rst.getObject(i+1);
                columnValueArr[i] = columnValue;
            }
        }
        return columnValueArr;
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(rst, pstmt, conn);
    }
    return null;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值