當應用中需要使用到上十張表時,DAO的維護變得日益困難,主要表現在這幾個方面:
1)dao類的繁多,很多設計都是一個entity對應一個dao
2)dao接口需要維護的method龐大。
3)業務邏輯改變時,dao需要同時修改兩個類文件(接口和實現類)
出於上述問題,有必要從新設計dao包。要求
1)減少dao類的數目,dao包暴露的接口穩定且易於擴展新的查詢。
2)減少dao接口的method
3)可以動態增加dao提供的數據訪問邏輯,比如增加相應的查詢實現等等
我的分析:
可以使用Criteria,NamedQuery來構造複雜的查詢邏輯。
對於改動最多的read/find邏輯,可以作一個抽象設計,以提供動態增加的同時提供穩定的接口。
對於update,create,delete邏輯,dao的設計遵循原子操作的原則,不在這些接口中實現複雜的業務邏輯。總體來說,這些接口的改動很少,也很容易規範。
下面是一些設計的類代碼:
[code="java"]
public interface QueryObject{
public void setNamedQuery(String qstring);
public Object query(Session session,Set parameterCollection);
public QueryCfg getQueryCfg();
public boolean validate(QuryCfg cfg,Set params) ;
public void setValidatable(boolean bool);
public booelan getValidatable();
}
public interface QueryCfg{
public List getParameterCfgs();
public String getName();
public void setName(String name);
}
public interface Parameter{
public ParameterCfg getParameterCfg();
public String getValue();
}
public interface ParameterCfg{
public int getOrder();
public void setOrder(int order);
public String getName();
public void setName(String name);
public Type getType();
public void setType();
}
public interface Type{
public static final String PRIMITIVE_TYPE="primitive";
public boolean isPrimitive();
public Class getObjectType();
public String getValue(Object o);
}
[/code]
上面這些基本接口便是組成我的dao包的設計基架。雖然與普通dao實現比較起來,這個設計多了許多複雜度,在項目初期也需要一定工作量來編碼實現這些構架,但是當在項目進展到中後期時,這個設計已經顯露了它優良的設計風格,它與普通DAO的設計相比較,有如下優點:
1)DAO的設計將會更加簡潔,用一個DAO接口就可以實現所有entity的dao操作,可以動態擴展複雜查詢。DAO設計:
[code="java"]public interface DAO{
// find 可以根據
public Object find(String namedQuery,Set parameters);
public Object createEntity(Object entity);
public Object updateEntity(Object entity);
public void removeEntity(Object entity);
}
//具體的實現可以整合到優秀的容器裏面。比如spring
publi class DAOImpl{
//....
public Object find(String name,Set ps){
return (Object)getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
return QueryLocator.getQueryObject(name).query(session,ps);
});
}
}
//其中QueryLocator的實現可以用Spring,PicoContainer等等。
[/code]
2)業務邏輯層依賴於一個較穩定的DAO接口,使得可以更獨立更快速的進行開發。
在業務邏輯層,他們可以這樣寫代碼:
[code="java"]public class YourBusiness{
public void doBusiness(){
Set parameters=new LinkedHashSet();
parameters.add("firstName","test");
parameters.add(2,"test2");
List users=(List)getDao.find("findUserWithFullName",parameters);
}
}[/code]
這裏的代碼依賴於一個穩定的DAO接口,而不需要先實現DAO修改,再回來做相應的業務實現。
3)可以支持參數檢查,因爲dao包的設計中加入了諸如ParameterCfg,QueryCfg等配置類,通過擴展這些抽象配置類實現我們定義的查詢的配置,可以有效地幫助我們檢查客戶端的非法查詢。
4)工作量統計。可以計算一下,dao增加一個新的複雜的查詢,需要增加一個QureyCfg類(可選,如果queryObject支持驗證參數,則需要否則不需要),一個QueryObject類,增加Spring的一個Bean配置。
傳統的DAO設計的話,需要修改一個DAO接口,修改DAO實現。
傳統的DAO設計對於增加或者修改查詢接口的話,工作量稍微少於我的設計。
當系統的表爲10個時,傳統的DAo設計一般需要產生10個dao類(需要接口的話,爲20個),如果一個dao類需要支持複雜的read查詢爲5個的話,對於查詢的method,至少需要50個method實現。
而我的設計除去Type這個底層穩定構架層次以外,僅僅需要一個DAO實現類,如果儘量採用NamedQuery,那麼整體QueryObject類實現一般僅僅需要10個左右即可,QueryObject還有利於抽象複雜的查詢,甚至包括需要使用到Criteria的QueryObject實現。比如這麼一個抽象:
[code="java"]public class CommonQuery implments QueryObject{
public Object query(Session session,Set parametes){
//驗證參數合法性
if(getValidatable())
validate(getQueryCfg(),parameters);
List res = session.createCriteria(parameters.get("type"))
.add( Expression.eq(parameters.get("queryParam"),parameters.get("value")))
.list();
}
}[/code]
他可以抽象對某個表的某個字段等於某值的查詢。
當然這些設計需要涉及到一個參數集合規範的問題,這些都是可以在項目初期很快設計明確下來以形成正式的QueryObject設計規範文檔。
整體評估:
當應用中的entity數量極大時,這種dao的設計將大大優越於傳統的dao設計。
簡化DAO設計的思想
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章
UML 常用符號簡明圖解
lcy9819
2020-02-22 23:52:08
Visual Architecting Process-Core
yaahoo1919
2018-09-01 18:32:19
Observer 觀察者
iteye_13864
2018-08-31 23:16:47
設計模式之Proxy(代理)
songzhi909
2018-08-25 11:58:35
設計模式之Bridge(橋模式)
songzhi909
2018-08-25 11:58:35
設計模式之Adapter(適配器)
songzhi909
2018-08-25 11:58:35
設計模式之Factory
songzhi909
2018-08-25 11:58:33
設計模式之Command
songzhi909
2018-08-25 11:58:33
Observer 觀察者
songzhi909
2018-08-25 11:58:33
從GOF的設計模式說起
songzhi909
2018-08-25 11:58:33
設計模式之Flyweight(享元)
songzhi909
2018-08-25 11:58:31