在传统的项目开发中我们会发现,无论是基于SSH框架,还是基于SSM框架。在后端持久层开发中,我们对各个模块的CRUD的操作基本上都是类似的。只是方法的 形参 和 返回值 不同。本文将基于Hibernate框架,利用Java反射机制对持久层进行封装,以达到简化开发、提高开发效率的目的。
代码重构前
传统的实现方式就是,在每一个模块里都要添加CRUD的操作,下面以CRM中的联系人和客户模块为例分析。
客户模块DAO接
客户模块DAO实现类
联系人模块DAO实现类
重构分析
对比以上两个实现类,我们发现两个实现类的方法只有方法的参数和返回值不同(对各个模块编写实现对应的方法时保证方法名保持一致,方便后期的抽取),我们可以向上抽取通用的dao的接口和实现类让我们自定义的各个模块来实现通用的dao的实现类。
分析接口
接口中的方法的参数和返回值可以使用泛型,来实现参数和返回值的数据类型接收。 如下
分析实现类
可以使用泛型 --> 表示通用的类型 来实现 基本的参数的传递 如果要传递某一个对象的 class 的对象,就不能利用传统的方式传递。
第一种方式: 通过构造方法传递 class对象,但是有侵入性
第二种方式: 通过反射的思想,获得 正在执行的 实际的参数化类型
当在添加一个模块的时候就可以,直接继承通用的接口的实现方法,里面就会有通用的方法,不用我们写重复的代码,提高代码的复用性。
具体实现的代码如下:
通用的接口 :public interface BaseDao {
public void save(T t);
public void update(T t);
public void delete(T t);
// 查询 public T findById(Long id);
// 查询多个:
public List findAll();
public Integer findCountByCondition(DetachedCriteria detachedCriteria);
public List findByCondition(DetachedCriteria detachedCriteria, Integer begin, Integer pageSize);
}
通用接口的实现类:public class BaseDaoImpl extends HibernateDaoSupport implements BaseDao {
// 构造方法将class值传递过来.(不建议)
private Class clazz ;
/*public BaseDaoImpl(Class clazz) {
this.clazz = clazz;
}*/
// 推荐
public BaseDaoImpl(){
// 获得子类的Class对象。
Class c = this.getClass();
// 正在执行的类的class对象.
// 获得当前子类上带有泛型的父类.
Type type = c .getGenericSuperclass();
// 就是一个参数化的类型.
BaseDaoImpl 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 findAll() {
/*DetachedCriteria detachedCriteria = DetachedCriteria.forClass(clazz);
return (List) this.getHibernateTemplate().findByCriteria(detachedCriteria);
*/
List list = (List) this .getHibernateTemplate().find( "from "+ clazz.getSimpleName()) ;
return list ;
}
@Override
public Integer findCountByCondition(DetachedCriteria detachedCriteria ) {
detachedCriteria .setProjection(Projections.rowCount());
List list = (List) this .getHibernateTemplate().findByCriteria( detachedCriteria );
if (list .size() > 0){
return list .get(0).intValue();
}
return null ;
}
@Override
public List findByCondition(DetachedCriteria detachedCriteria , Integer begin , Integer pageSize) {
detachedCriteria .setProjection(null);
return (List) this .getHibernateTemplate().findByCriteria( detachedCriteria , begin , pageSize);
}
}
新添加一个模块时的简单的实现:public interface LinkManDao extends BaseDao{
}
public class LinkManDaoImpl extends BaseDaoImpl implements LinkManDao {
}
这样在新加模块时,对单表的CRUD以及分页就可以直接BaseDao接口即可。如果需要自定义相关方法,那么可以在当前模块下添加特有方法实现即可。所以大大提高了代码的复用性和开发的效率。
猜你喜欢:java高级软件工程师课程