Java反射封装公有DAO

现在都是用框架去开发,既简单又快速,给我们提供了很多便利;有利便有弊,坏处就是依赖框架,忘记了Java基础,不在关注底层是怎么实现的,这里大家一起回顾一下最原始的jdbc写法:

第一步:导入jar包,这里不多说了,百度都有;

第二步:创建BaseDao(偷下懒,把所有方法都写在一个类里面了),上代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 公共dao类
 */
@Component
public class BaseDao<T> {

    private final Logger logger = LoggerFactory.getLogger(BaseDao.class);
    private Connection conn = null;
    private PreparedStatement ps = null;
    private ResultSet rs = null;


    /**
     * 建立数据库连接
     * @return
     */
    private Connection getConnection() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");

            if (!conn.isClosed()) {
                logger.info("################# 数据库连接成功 #################");
            }
        } catch (ClassNotFoundException e) {
            logger.error("加载jdbc.Driver异常", e);
            throw new RuntimeException("加载jdbc.Driver异常", e);
        } catch (SQLException e) {
            logger.error("建立数据库连接异常", e);
            throw new RuntimeException("建立数据库连接异常", e);
        }
        return conn;
    }

    /**
     * 方法用途: 公共查询方法,返回List集合<br/>
     * 操作步骤: TODO<br/>
     * ${tags}
     */
    public <T> List<?> queryList(Class<T> clazz, String sql, Object... params) {
        T t;
        List<T> list = new ArrayList<>();
        logger.info(sql);
        logger.info(null == params? "" : params.toString());

        try {
            Field[] fields = getAllFields(clazz);
            conn = getConnection();
            ps = conn.prepareStatement(sql);
            initParams(ps, params);
            rs = ps.executeQuery();
            // 返回结果集
            while (rs.next()) {
                t = getObjResult(fields, rs, clazz);
                list.add(t);
            }
            logger.info(String.format("################# 查询成功,共%s条记录 #################", list.size()));
        } catch (SQLException e) {
            logger.error("执行查询异常", e);
            throw new RuntimeException("执行查询异常", e);
        } finally {
            // 关闭数据库连接
            closeDb(rs, ps, conn);
        }
        return list;
    }

    /**
     * 将每行结果存入map集合,对象属性名为key,查询出的结果为value
     * @param fields
     * @param rs
     * @return
     */
    private <T> T getObjResult(Field[] fields, ResultSet rs, Class<T> clazz) {
        T t = null;
        Field field;
        Method method;
        String fieldName;
        String fieldType;

        try {
            t = clazz.newInstance();
            for (int i = 0; i < fields.length; i++) {
                field = fields[i];
                field.setAccessible(true);
                fieldName = field.getName();
                if (fieldName.equals("serialVersionUID")) {
                    continue;
                }
                fieldType = field.getType().getName();
                method = getMethod(clazz, field, fieldName, fieldType);
                Object value = rs.getObject(initField(fieldName));
                if (fieldType.equals("java.lang.String")) {
                    method.invoke(t, value);
                } else if (fieldType.equals("java.lang.Integer")) {
                    method.invoke(t, Integer.valueOf(value.toString()));
                }
            }
        } catch (SQLException e) {
            logger.error("rs获取结果异常", e);
            throw new RuntimeException("rs获取结果异常", e);
        } catch (InvocationTargetException e) {
            logger.error("method.invoke方法执行异常", e);
            throw new RuntimeException("method.invoke方法执行异常", e);
        } catch (IllegalAccessException e) {
            logger.error("method.invoke方法执行异常", e);
            throw new RuntimeException("method.invoke方法执行异常", e);
        } catch (InstantiationException e) {
            logger.error("建立T对象异常", e);
            throw new RuntimeException("建立T对象异常", e);
        }
        return t;
    }

    /**
     * 对象属性的set方法
     * @param clazz
     * @param field
     * @param fieldName
     * @param fieldType
     * @return
     */
    private Method getMethod(Class clazz, Field field, String fieldName, String fieldType){
        Method method = null;
        try {
            if (fieldType.equals("java.lang.Boolean")) {
                method = clazz.getDeclaredMethod("is" + getMethodName(fieldName), field.getType());
            } else {
                method = clazz.getDeclaredMethod("set" + getMethodName(fieldName), field.getType());
            }
        } catch (NoSuchMethodException e) {
            Class superClazz = clazz.getSuperclass();
            method = getMethod(superClazz, field, fieldName, fieldType);
        }
        return method;
    }

    /**
     * 获取所有属性(getSuperclass:获取父类属性)
     * @param clazz
     * @param <T>
     * @return
     */
    private <T> Field[] getAllFields(Class<T> clazz) {
        Class superClazz = clazz;
        List<Field> fieldList = new ArrayList<>();
        while (null != superClazz) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(superClazz.getDeclaredFields())));
            superClazz = superClazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

    /**
     * 将驼峰属性名转换为带下划线字段(xx_xx)
     * @param field
     * @return
     */
    private String initField(String field) {
        StringBuilder newField = new StringBuilder();
        for (int i = 0; i < field.length(); i++) {
            char c = field.charAt(i);
            if (Character.isUpperCase(c)) {
                newField.append("_").append(Character.toLowerCase(c));
            } else {
                newField.append(c);
            }
        }
        return newField.toString();
    }

    /**
     * 组装参数
     * @param ps
     * @param params
     */
    private void initParams(PreparedStatement ps, Object... params) {
        if (null != params && params.length > 0) {
            try {
                for (int i = 0; i < params.length; i++) {
                    ps.setString(i, params[i].toString());
                }
            } catch (SQLException e) {
                logger.error("ps设置参数异常", e);
                throw new RuntimeException("ps设置参数异常", e);
            }
        }
    }

    /**
     * 方法用途: 把一个字符串的第一个字母大写、效率是最高的<br/>
     * 操作步骤: TODO<br/>
     * ${tags}
     */
    private static String getMethodName(String fildeName) {
        byte[] items = fildeName.getBytes();
        items[0] = (byte) ((char) items[0] - 'a' + 'A');
        return new String(items);
    }

    /**
     * 关闭数据库连接
     * @param rs
     * @param ps
     * @param conn
     */
    private void closeDb(ResultSet rs, PreparedStatement ps, Connection conn) {
        try {
            if (null != rs) {
                rs.close();
            }

            if (null != ps) {
                ps.close();
            }

            if (null != conn) {
                conn.close();
            }

            logger.info("################# 连接关闭成功 #################");
        } catch (SQLException e) {
            logger.error("关闭连接异常", e);
            throw new RuntimeException("关闭连接异常", e);
        }
    }
}

好了,都是我手敲出来的代码,注释也都加上了,不懂的多读几遍代码吧,实在看不明白先回顾下Java反射的基础(Java反射基础案例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值