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