通用DAO

1. 定义通用Dao接口

package utils;

import java.util.List;

/**
 * @Description:泛型通用Dao接口
 * @Author one world
 * @Date 2020/9/20 0020 17:25
 */
public interface GenicaDao<T,PK>  {
    /**
     * 分页查询所有
     * @param currentPage
     * @param limit
     * @return List
     */
    public List<T> findAll(Integer currentPage, Integer limit);

    /**
     * 查询所有
     * @return List
     */

    public List<T> findAll();

    /**
     * 根据主键查询实体
     * @param id
     * @return T
     */
    public T findByPK(PK id);

    /**
     * 根据主键删除
     * @param id
     * @return true/false
     */
    public boolean delByPK(PK id);

    /**
     * 添加
     * @param t
     * @return true/false
     */
    public boolean add(T t);

    /**
     * 更新
     * @param t
     * @return true/false
     */
    public boolean update(T t);
}

2.通用DAO的实现类

package utils;


import annotion.Column;
import annotion.Id;
import annotion.Relation;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 泛型Dao通用方法
 * @Author one world
 * @Date 2020/9/20 0020 17:11
 */
public class GenicaDaoImpl<T, PK extends Serializable> implements GenicaDao<T, PK> {
    private Class<T> tClazz = null;//实体Class
    private Class<PK> pkClazz = null;//主键Class
    String tableName = null;//表名
    String pk = null;//注解中的主键名
    private static final Logger logger = LoggerFactory.getLogger(GenicaDaoImpl.class);

    /**
     * 构造方法初始化属性
     */
    public GenicaDaoImpl() {
        tClazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        pkClazz = (Class<PK>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1];
        tableName = DaoUtil.getTable(tClazz);
        pk = DaoUtil.getPK(tClazz);
    }

    /**
     * 分页查询所有
     *
     * @param currentPage
     * @param limit
     * @return
     */
    @Override
    public List<T> findAll(Integer currentPage, Integer limit) {
        currentPage = (currentPage - 1) * limit;
        String sql = "select * from " + tableName + " limit ?,?";
        return DaoUtil.queryList(tClazz, sql, currentPage, limit);
    }

    /**
     * 查询所有
     *
     * @return
     */
    @Override
    public List<T> findAll() {
        String sql = "select * from " + tableName;
        return DaoUtil.queryList(tClazz, sql);
    }

    /**
     * 根据主键查询实体
     *
     * @param id
     * @return true/false
     */
    @Override
    public T findByPK(PK id) {
        T t = null;
        String sql = "select * from " + tableName + " where " + pk + "=?";
        t = DaoUtil.query(tClazz, sql, id);
        return t;
    }

    /**
     * 根据主键删除
     *
     * @param id
     * @return true/false
     */
    @Override
    public boolean delByPK(PK id) {
        String sql = "delete from " + tableName + " where " + pk + "=?";
        return DaoUtil.update(sql, id);
    }

    /**
     * 向数据库添加
     *
     * @param t
     * @return true/false
     */
    @Override
    public boolean add(T t) {
        String sql = "insert into " + tableName + "(";
        StringBuffer sb = new StringBuffer(sql);
        Map map = DaoUtil.getNameAndValue(tClazz);
        Object[] params = new Object[tClazz.getDeclaredFields().length - 1];
        String id = DaoUtil.getPK(tClazz);
        int index = 0;
        try {
            for (Object key : map.keySet()) {
                String methodName = "get" + getName(map.get(key).toString());
                Method method = tClazz.getDeclaredMethod(methodName);
                Field field = tClazz.getDeclaredField(map.get(key).toString());
                if (id != key&&!field.isAnnotationPresent(Relation.class)) {
                    params[index] = method.invoke(t);
                    sb.append(key.toString() + ",");
                    index++;
                }
                if(field.isAnnotationPresent(Relation.class)){
                    Field[] rfields = field.getType().getDeclaredFields();
                    for(Field rfield: rfields){
                        if (rfield.isAnnotationPresent(Id.class)){
                            rfield.setAccessible(true);
                            String rMethodName = "get"+getName(rfield.getName());
                            Method rMethod = field.getType().getDeclaredMethod(rMethodName);
                            params[index]=rMethod.invoke(method.invoke(t));
                            index++;
                            break;
                        }
                    }
                    sb.append(key.toString() + ",");
                }
            }
            sb = new StringBuffer(sb.substring(0,sb.length()-1));
            sb.append(") values(");
            for(int i=0;i<index;i++){
                if(i+1!=index){
                    sb.append("?,");
                }else {
                    sb.append("?)");
                }
            }
            return DaoUtil.update(sb.toString(), params);
        } catch (NoSuchMethodException | IllegalAccessException |InvocationTargetException |NoSuchFieldException e) {
            logger.error("GenicaDaoImpl类add方法异常",e);
        }
        return false;
    }

    /**
     * 更新指定记录
     *
     * @param t
     * @return
     */
    @Override
    public boolean update(T t) {
        StringBuffer sb = new StringBuffer("update " + tableName + " set ");
        Field[] fields = tClazz.getDeclaredFields();
        //用于存放参数,存放完毕后直接传入DaoUtil工具类进行操作
        Object[] params = new Object[fields.length + 1];
        //标记,用于标记字段是否为id字段
        boolean flag = false;
        //主键字段
        Object id = null;
        try {
            for (int i = 0; i < fields.length; i++) {
                fields[i].setAccessible(true);
                String methodName = "get" + getName(fields[i].getName());
                Method method = tClazz.getDeclaredMethod(methodName);
                if (fields[i].isAnnotationPresent(Id.class)) {
                    String pk = fields[i].getAnnotation(Id.class).value();
                    if (pk == null || pk.equals("")) {
                        sb.append(fields[i].getName() + "=?");
                    } else {
                        sb.append(pk + "=?");
                    }
                    flag = true;
                    params[i] = method.invoke(t);
                } else if (fields[i].isAnnotationPresent(Column.class)) {
                    sb.append(fields[i].getAnnotation(Column.class).value() + "=?");
                    params[i] = method.invoke(t);
                } else if (fields[i].isAnnotationPresent(Relation.class)) {
                    Object fk = null;
                    sb.append(fields[i].getAnnotation(Relation.class).value() + "=?");
                    Field[] rfields = fields[i].getType().getDeclaredFields();
                    for (Field rfield : rfields) {
                        if (rfield.isAnnotationPresent(Id.class)) {
                            rfield.setAccessible(true);
                            String rMethodName = "get" + getName(rfield.getName());
                            Method rMethod = fields[i].getType().getDeclaredMethod(rMethodName);
                            fk = rMethod.invoke(method.invoke(t));
                            System.out.println(fk);
                            break;
                        }
                    }
                    params[i] = fk;
                } else {
                    sb.append(fields[i].getName() + "=?");
                    params[i] = method.invoke(t);
                }
                if (i + 1 != fields.length) {
                    sb.append(",");
                }
                if (flag) {
                    params[fields.length] = params[i];
                    //清除标记,防止字段读取异常
                    flag = false;
                }
            }
            sb.append(" where " + pk + "=?");
            return DaoUtil.update(sb.toString(), params);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            logger.error("GenicaDaoImpl类update方法异常",e);
        }
        return false;
    }

    /**
     * 将字段名首字母大写,返回拼接完整的方法名,反射调用方法
     *
     * @param name
     * @return
     */
    public static String getName(String name) {
        name = name.substring(0, 1).toUpperCase() + name.substring(1);
        return name;
    }

}

3.接口继承于接口

package dao;

import model.RotationImg;
import utils.GenicaDao;

/**
 * @Description:
 * @Author one world
 * @Date 2020/9/21 0021 20:20
 */
public interface RotationImgDao extends GenicaDao<RotationImg,Integer> {
}

4.实现类继承于实现类

package dao.impl;

import dao.RotationImgDao;
import model.RotationImg;
import utils.GenicaDao;
import utils.GenicaDaoImpl;

/**
 * @Description:
 * @Author one world
 * @Date 2020/9/21 0021 20:20
 */
public class RotationImgDaoImpl extends GenicaDaoImpl<RotationImg,Integer> implements RotationImgDao {
}
为什么我们要使用通用DAO接口呢,因为我们的数据库操作无非是增删改查,CRUD操作,我们不需要为每个实体去编写一个dao接口,对于相似的实体操作可以只编写一个通用接口,然后采用不同的实现! DAO已经成为持久层的标准模式,DAO使结构清晰,面向接口编程为代码提供了规范。而泛型DAO是一个类型安全的,代码精简的设计模式(相对于传统DAO),尤其在DAO组件数量庞大的时候,代码量的减少更加明显。 泛型DAO的核心是定义一个GenericDao接口,声明基本的CRUD操作: 用hibernate作为持久化解决方案的GenericHibernateDao实现类,被定义为抽象类,它提取了CRUD操作,这就是简化代码的关键,以便于更好的重用,这个就不给例子了,增删改都好写,查就需要各种条件了。 然后是各个领域对象的dao接口,这些dao接口都继承GenericDao接口,这样各个领域对象的dao接口就和传统dao接口具有一样的功能了。 下一步是实现类了,个自领域对象去实现各自的接口,还要集成上面的抽象类,这样就实现了代码复用的最大化,实现类中只需要写出额外的查询操作就可以了。当然还要获得域对象的Class实例,这就要在构造方法中传入Class实例。用spring提供的HibernateTemplate注入到GenericHibernateDao中,这样在各个实现类就可以直接调用HibernateTemplate来实现额外的查询操作了。 如果在实现类中不想调用某个方法(例如:update()),就可以覆盖它,方法中抛出UnsupportedOperationException()异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SinceThenLater

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值