首頁技術文章正文

反射機制應用:DAO抽取通用層實現(xiàn)

更新時間:2020-11-06 來源:黑馬程序員 瀏覽量:

在傳統(tǒng)的項目開發(fā)中我們會發(fā)現(xiàn),無論是基于SSH框架,還是基于SSM框架。在后端持久層開發(fā)中,我們對各個模塊的CRUD的操作基本上都是類似的。只是方法的 形參 和 返回值 不同。本文將基于Hibernate框架,利用Java反射機制對持久層進行封裝,以達到簡化開發(fā)、提高開發(fā)效率的目的。

代碼重構前

傳統(tǒng)的實現(xiàn)方式就是,在每一個模塊里都要添加CRUD的操作,下面以CRM中的聯(lián)系人和客戶模塊為例分析。

客戶模塊DAO接

客戶模塊DAO實現(xiàn)類

聯(lián)系人模塊DAO實現(xiàn)類

重構分析

對比以上兩個實現(xiàn)類,我們發(fā)現(xiàn)兩個實現(xiàn)類的方法只有方法的參數和返回值不同(對各個模塊編寫實現(xiàn)對應的方法時保證方法名保持一致,方便后期的抽取),我們可以向上抽取通用的dao的接口和實現(xiàn)類讓我們自定義的各個模塊來實現(xiàn)通用的dao的實現(xiàn)類。

分析接口

接口中的方法的參數和返回值可以使用泛型,來實現(xiàn)參數和返回值的數據類型接收。 如下

分析實現(xiàn)類

可以使用泛型 --> 表示通用的類型 來實現(xiàn) 基本的參數的傳遞 如果要傳遞某一個對象的 class 的對象,就不能利用傳統(tǒng)的方式傳遞。

第一種方式: 通過構造方法傳遞 class對象,但是有侵入性

第二種方式: 通過反射的思想,獲得 正在執(zhí)行的 實際的參數化類型

當在添加一個模塊的時候就可以,直接繼承通用的接口的實現(xiàn)方法,里面就會有通用的方法,不用我們寫重復的代碼,提高代碼的復用性。


具體實現(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); 
    // 查詢多個: 
    public List<T> findAll(); 
    public Integer findCountByCondition(DetachedCriteria detachedCriteria); 
    public List<T> findByCondition(DetachedCriteria detachedCriteria, Integer begin, Integer pageSize);
}


通用接口的實現(xiàn)類:

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(); 
        // 正在執(zhí)行的類的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); 
    }
}

新添加一個模塊時的簡單的實現(xiàn):

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


這樣在新加模塊時,對單表的CRUD以及分頁就可以直接BaseDao接口即可。如果需要自定義相關方法,那么可以在當前模塊下添加特有方法實現(xiàn)即可。所以大大提高了代碼的復用性和開發(fā)的效率。


猜你喜歡:
java高級軟件工程師課程


分享到:
在線咨詢 我要報名
和我們在線交談!