首页技术文章正文

反射机制应用:DAO抽取通用层实现

更新时间:2020-11-06 来源:黑马程序员 浏览量:

在传统的项目开发中我们会发现,无论是基于SSH框架,还是基于SSM框架。在后端持久层开发中,我们对各个模块的CRUD的操作基本上都是类似的。只是方法的 形参 和 返回值 不同。本文将基于Hibernate框架,利用Java反射机制对持久层进行封装,以达到简化开发、提高开发效率的目的。

代码重构前

传统的实现方式就是,在每一个模块里都要添加CRUD的操作,下面以CRM中的联系人和客户模块为例分析。

客户模块DAO接

客户模块DAO实现类

联系人模块DAO实现类

重构分析

对比以上两个实现类,我们发现两个实现类的方法只有方法的参数和返回值不同(对各个模块编写实现对应的方法时保证方法名保持一致,方便后期的抽取),我们可以向上抽取通用的dao的接口和实现类让我们自定义的各个模块来实现通用的dao的实现类。

分析接口

接口中的方法的参数和返回值可以使用泛型,来实现参数和返回值的数据类型接收。 如下

分析实现类

可以使用泛型 --> 表示通用的类型 来实现 基本的参数的传递 如果要传递某一个对象的 class 的对象,就不能利用传统的方式传递。

第一种方式: 通过构造方法传递 class对象,但是有侵入性

第二种方式: 通过反射的思想,获得 正在执行的 实际的参数化类型

当在添加一个模块的时候就可以,直接继承通用的接口的实现方法,里面就会有通用的方法,不用我们写重复的代码,提高代码的复用性。


具体实现的代码如下:

通用的接口 :

public interface BaseDao<T> { 
    public void save(T t); 
    public void update(T t); 
    public void delete(T t); 
    // 查询 public T findById(Long id); 
    // 查询多个: 
    public List<T> findAll(); 
    public Integer findCountByCondition(DetachedCriteria detachedCriteria); 
    public List<T> findByCondition(DetachedCriteria detachedCriteria, Integer begin, Integer pageSize);
}


通用接口的实现类:

public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> { 
    // 构造方法将class值传递过来.(不建议) 
    private Class clazz ; 
    /*public BaseDaoImpl(Class clazz) { 
        this.clazz = clazz; 
    }*/
    // 推荐 
    public BaseDaoImpl(){ 
        // 获得子类的Class对象。 
        Class c = this.getClass(); 
        // 正在执行的类的class对象. 
        // 获得当前子类上带有泛型的父类. 
        Type type = c .getGenericSuperclass(); 
        // 就是一个参数化的类型. 
        BaseDaoImpl<Customer> System. out .println("type=======" +type ); 
        // 将type转为参数化类型 
        if (type instanceof ParameterizedType){ 
            ParameterizedType pType = (ParameterizedType) type ;
            // 转为参数化类型. // 通过参数的类型获得实际类型参数: 
            Type[] types = pType .getActualTypeArguments();
            // 获得实际类型参数的数组.Customer 
            this .clazz = (Class) types [0]; 
        }
    }
    @Override 
    public void save(T t ) { 
        this .getHibernateTemplate().save(t ); 
    } 
    @Override 
    public void update(T t ) {
        this .getHibernateTemplate().update(t );
    } 
    @Override 
    public void delete(T t ) { 
        this .getHibernateTemplate().delete(t ); 
    } 
    @Override 
    public T findById(Long id) { 
        return (T) this .getHibernateTemplate().get( clazz, id) ; 
    }
    @Override 
    public List<T> findAll() { 
        /*DetachedCriteria detachedCriteria = DetachedCriteria.forClass(clazz); 
        return (List<T>) this.getHibernateTemplate().findByCriteria(detachedCriteria);
        */ 
        List<T> list = (List<T>) this .getHibernateTemplate().find( "from "+ clazz.getSimpleName()) ;
        return list ; 
    }
    @Override 
    public Integer findCountByCondition(DetachedCriteria detachedCriteria ) { 
        detachedCriteria .setProjection(Projections.rowCount()); 
        List<Long> list = (List<Long>) this .getHibernateTemplate().findByCriteria( detachedCriteria ); 
        if (list .size() > 0){ 
            return list .get(0).intValue(); 
        } 
        return null ; 
    } 
    @Override 
    public List<T> findByCondition(DetachedCriteria detachedCriteria , Integer begin , Integer pageSize) { 
        detachedCriteria .setProjection(null); 
        return (List<T>) this .getHibernateTemplate().findByCriteria( detachedCriteria , begin , pageSize); 
    }
}

新添加一个模块时的简单的实现:

public interface LinkManDao extends BaseDao<LinkMan>{ 
} 
public class LinkManDaoImpl extends BaseDaoImpl<LinkMan> implements LinkManDao { 
    
}


这样在新加模块时,对单表的CRUD以及分页就可以直接BaseDao接口即可。如果需要自定义相关方法,那么可以在当前模块下添加特有方法实现即可。所以大大提高了代码的复用性和开发的效率。


猜你喜欢:
java高级软件工程师课程


分享到:
在线咨询 我要报名
和我们在线交谈!