更新時(shí)間:2020-11-06 來源:黑馬程序員 瀏覽量:
在傳統(tǒng)的項(xiàng)目開發(fā)中我們會(huì)發(fā)現(xiàn),無論是基于SSH框架,還是基于SSM框架。在后端持久層開發(fā)中,我們對(duì)各個(gè)模塊的CRUD的操作基本上都是類似的。只是方法的 形參 和 返回值 不同。本文將基于Hibernate框架,利用Java反射機(jī)制對(duì)持久層進(jìn)行封裝,以達(dá)到簡化開發(fā)、提高開發(fā)效率的目的。
代碼重構(gòu)前
傳統(tǒng)的實(shí)現(xiàn)方式就是,在每一個(gè)模塊里都要添加CRUD的操作,下面以CRM中的聯(lián)系人和客戶模塊為例分析。
客戶模塊DAO接
客戶模塊DAO實(shí)現(xiàn)類
聯(lián)系人模塊DAO實(shí)現(xiàn)類
重構(gòu)分析
對(duì)比以上兩個(gè)實(shí)現(xiàn)類,我們發(fā)現(xiàn)兩個(gè)實(shí)現(xiàn)類的方法只有方法的參數(shù)和返回值不同(對(duì)各個(gè)模塊編寫實(shí)現(xiàn)對(duì)應(yīng)的方法時(shí)保證方法名保持一致,方便后期的抽取),我們可以向上抽取通用的dao的接口和實(shí)現(xiàn)類讓我們自定義的各個(gè)模塊來實(shí)現(xiàn)通用的dao的實(shí)現(xiàn)類。
分析接口
接口中的方法的參數(shù)和返回值可以使用泛型,來實(shí)現(xiàn)參數(shù)和返回值的數(shù)據(jù)類型接收。 如下
分析實(shí)現(xiàn)類
可以使用泛型 --> 表示通用的類型 來實(shí)現(xiàn) 基本的參數(shù)的傳遞 如果要傳遞某一個(gè)對(duì)象的 class 的對(duì)象,就不能利用傳統(tǒng)的方式傳遞。
第一種方式: 通過構(gòu)造方法傳遞 class對(duì)象,但是有侵入性
第二種方式: 通過反射的思想,獲得 正在執(zhí)行的 實(shí)際的參數(shù)化類型
當(dāng)在添加一個(gè)模塊的時(shí)候就可以,直接繼承通用的接口的實(shí)現(xiàn)方法,里面就會(huì)有通用的方法,不用我們寫重復(fù)的代碼,提高代碼的復(fù)用性。
具體實(shí)現(xiàn)的代碼如下:
通用的接口 :
public interface BaseDao<T> { public void save(T t); public void update(T t); public void delete(T t); // 查詢 public T findById(Long id); // 查詢多個(gè): public List<T> findAll(); public Integer findCountByCondition(DetachedCriteria detachedCriteria); public List<T> findByCondition(DetachedCriteria detachedCriteria, Integer begin, Integer pageSize); }
通用接口的實(shí)現(xiàn)類:
public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> { // 構(gòu)造方法將class值傳遞過來.(不建議) private Class clazz ; /*public BaseDaoImpl(Class clazz) { this.clazz = clazz; }*/ // 推薦 public BaseDaoImpl(){ // 獲得子類的Class對(duì)象。 Class c = this.getClass(); // 正在執(zhí)行的類的class對(duì)象. // 獲得當(dāng)前子類上帶有泛型的父類. Type type = c .getGenericSuperclass(); // 就是一個(gè)參數(shù)化的類型. BaseDaoImpl<Customer> System. out .println("type=======" +type ); // 將type轉(zhuǎn)為參數(shù)化類型 if (type instanceof ParameterizedType){ ParameterizedType pType = (ParameterizedType) type ; // 轉(zhuǎn)為參數(shù)化類型. // 通過參數(shù)的類型獲得實(shí)際類型參數(shù): Type[] types = pType .getActualTypeArguments(); // 獲得實(shí)際類型參數(shù)的數(shù)組.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); } }
新添加一個(gè)模塊時(shí)的簡單的實(shí)現(xiàn):
public interface LinkManDao extends BaseDao<LinkMan>{ } public class LinkManDaoImpl extends BaseDaoImpl<LinkMan> implements LinkManDao { }
這樣在新加模塊時(shí),對(duì)單表的CRUD以及分頁就可以直接BaseDao接口即可。如果需要自定義相關(guān)方法,那么可以在當(dāng)前模塊下添加特有方法實(shí)現(xiàn)即可。所以大大提高了代碼的復(fù)用性和開發(fā)的效率。
猜你喜歡:
java高級(jí)軟件工程師課程