更新时间: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高级软件工程师课程