dao設計
⑴ 什麼是DAO設計模式
DAO設計模式學習沖刺(8個月) 2009-04-07 18:04 閱讀88 評論0 字型大小: 大大 中中 小小 DAO設計模式 DAO(Data Access Object)模式實際上是兩個模式的組合,即Data Accessor 模式和 Active Domain Object 模式,其中 Data Accessor 模式實現了數據訪問和業務邏輯的分離,而Active Domain Object 模式,其中Data Accessor模式實現了數據訪問和業務邏輯的分離,而Active Domain Object 模式實現了業務數據的對象化封裝,一般我們將這兩個模式組合使用,因此,考慮到這些因素,這里將其作為同一個主題加以討論。如圖展示了DAO模式的實現層次。
DAO模式通過對業務層提供數據抽象層介面,實現了以下目標:
1. 數據存儲邏輯的分離
通過對數據訪問邏輯進行抽象,為上層機構提供抽象化的數據訪問介面。業務層無需關心具體的select,insert,update操作,這樣,一方面避免了業務代碼中混雜JDBC調用語句,使得業務落實實現更加清晰,另一方面,由於數據訪問幾口語數據訪問實現分離,也使得開發人員的專業劃分成為可能。某些精通資料庫操作技術的開發人員可以根據介面提供資料庫訪問的最優化實現,而精通業務的開發人員則可以拋開數據曾德繁瑣細節,專注於業務邏輯編碼。
2. 數據訪問底層實現的分離
DAO模式通過將數據訪問計劃分為抽象曾和實現曾,從而分離了數據使用和數據訪問的地稱實現細節。這意味著業務層與數據訪問的底層細節無關,也就是說,我們可以在保持上層機構不變得情況下,通過切換底層實現來修改數據訪問的具體機制,常見的一個例子就是,我們可以通過僅僅替換數據訪問曾實現,將我們的系統部署在不同的資料庫平台之上。
3. 資源管理和調度的分離
在資料庫操作中,資源的管理和調度是一個非常值得關注的主題。大多數系統的性能瓶頸往往並非集中於業務邏輯處理本身。在系統涉及的各種資源調度過程中,往往存在著最大的性能黑洞,而資料庫作為業務系統中最重要的系統資源,自然也成為關注的焦點。DAO模式將數據訪問邏輯從業務邏輯中脫離開來,使得在數據訪問層實現統一的資源調度成為可能,通過資料庫連接池以及各種緩存機制(Statement Cache,Data Cache等,緩存的使用是高性能系統實現的一個關鍵所在)的配合使用,往往可以保持上層系統不變的情況下,大幅度提升系統性能。
4.數據抽象
在直接基於JDBC調用的代碼中,程序員面對的數據往往是原始的RecordSet數據集,誠然這樣的數據集可以提供足夠的信息,但對於業務邏輯開發過程而言,如此瑣碎和缺乏寓意的欄位型數據實在令人厭倦。
DAO 模式通過對底層數據的封裝,為業務曾提供一個面向對象的介面,使得業務邏輯開發員可以面向業務中的實體進行編碼。通過引入DAO模式,業務邏輯更加清晰,且富於形象性和描述性,這將為日後的維護帶來極大的便利。試想,在業務曾通過Customer.getName方法獲得客戶姓名,相對於直接通過SQL語句訪問資料庫表並從ResultSet中獲得某個字元型欄位而言,哪種方式更加易於業務邏輯的形象化和簡潔化?
空洞地談些理論固然沒有什麼價值,我們需要看到的是通過對應用設計模式之後,我們的代碼到底有怎樣的改觀,進而才能對設計帶來的優劣有所感悟。下面讓我們來看看代碼:
[code]Public BigDecimal calcAmount(String customerID,BigDecimal amount){ //根據客戶ID獲得客戶記錄 Customer customer = CustomerDAO.getCustomer(customerID); //根據客戶登記獲得打折規則 Promotion promotion = PromotionDAO.getPromotion(customer.getLevel()); //累積客戶總消費額,並保存累計結果 Customer.setSumAmount(customer.getSumAmount().add(amount)); CustomerDAO.save(customer); //返回打折後金額 Return amount.multiply(promotion.getRatio()); }[/code]這樣的代碼相信已經足夠明晰,即使對於缺乏資料庫技術基礎的讀者也可以輕松閱讀。
從上面這段代碼中,我們可以看到,通過DAO模式對各個資料庫對象進行封裝,我們對業務層屏蔽了資料庫訪問的底層實現,業務曾僅包含與本領域相關的邏輯對象和演算法,這樣對於業務邏輯開發人員(以及日後專注於業務邏輯的代碼閱讀者)而言,面對的是一個簡潔明快的邏輯實現結構。業務層的開發和維護將變得更加簡單。
DAO模式中,資料庫訪問層實現被隱藏到Data Accessor中,前面說過,DAO模式實際上是兩個模式的組合,即Data Accessor 和 Domain Object模式。
何謂 Data Accessor?即將數據訪問的實現機制加以封裝,與數據的使用代碼相分離,從外部來看,Data Accessor 提供了黑盒式的數據存取介面。
Domain Object則提供了對所面向領域內對象的封裝。
從某種意義上,我們可以這么理解:
[code]Data Accessor object (DAO) =Data +Accessor + domain object[/code]
這個等式自左向右,形象地描述了設計分離的3個層次。
現在,對於上面的例子,來看看業務層後所隱藏的實現細節:
首先,我們這個計算打折後金額的業務過程中,涉及了兩個業務對象,即客戶對象Customer,和促銷規則對象Promotion。自然,這兩個對象也就成為了此業務領域(Business Domain)中的Domain Object,所謂Domain Object,簡單來講就是對領域內(Domain)涉及的各個數據對象,反映到代碼,就是一個擁有相關屬性的getter,setter方法的JavaClass(Java Bean)
以Customer和CustomerDao為例,實現代碼如下(Promotion 和 PromotionDAO的實現代碼與此類似):
DAO 模式的進一步改良
上面的例子中我們通過DAO模式實現了業務路基與數據邏輯的分離。對於專項開發(為特定客戶環境指定的特定業務系統)而言,這樣的分離設計差不多已經可以實現開發過程中業務層面與數據層面的相對獨立,並且在實現復雜性與結構清晰性上達到較好的平衡。
然而,對於一個產品化的業務系統而言,目前的設計卻仍稍顯不足。相對專項原發的軟體項目而言,軟體產品往往需要在不同客戶環境下及時部署。一個典型情況就是常見的論壇系統,一個商業論壇系統可能會部署在廠前上萬個不同的客戶環境中。誠然,由於java良好的跨平台支持,我們在操作系統之間大可輕易遷移,但在另外一個層面,資料庫層,卻仍然面臨著平台遷移的窘境。客戶可能已經購買了Oracle,SQLServer,Sybase 或者其他類型的 資料庫。這就意味著我們的產品必須能部署在這些平台上,才能滿足客戶的需求。
對於我們現有的設計而言,為了滿足不同客戶的需求,我們可以實現針對不同類型資料庫的
Data Accessor,並根據客戶實際部署環境,通過類文件的靜態替換來實現。顯然,這樣的實現方式在面對大量客戶和復雜的部署環境時,將大大增加部署和維護工作的難度和復雜性。回憶一下「開閉原則」(Open-Close Principle) –對擴展開放,對修改封閉。我們應該採取適當的設計,將此類因素帶來的變動(類的靜態替換)屏蔽在系統之外。
為了實現跨資料庫平台移植,或者展開來說,為了支持不同數據訪問機制之間的可配置切換,我們需要在目前的DAO層引入Factory模式和Proxy模式。
這里所謂的不同數據訪問機制,包括了不同資料庫本身的訪問實現,同時也包括了對於同一資料庫德不同訪問機制的兼容。例如我們的系統部署在小客戶環境中,可能採用了基於JDBC的實現,而在企業環境中部署時,可能採用CMP作為數據訪問的底層實現,以獲得伺服器集群上的性能優勢(CMP具體怎樣還有待商榷,這里暫且將其作為一個理由)。
Factory模式的引入
由於需要針對不同的資料庫訪問機制分別提供各自版本的Data Accessor實現,自然我們會想通過 Java Interface 定義一個調用介面,然後對這個調用介面實現不同資料庫的 Data Accessor。通過以介面作為調用界面和實現規范,我們就可以避免代碼只能給對具體實現的依賴。
對於例子中的CustomerDAO而言,我們可以抽象出如下的介面:
[code]Public interface CustomerDAO{ Public Customer getCustomer(String custID); Puboic void save (Customer customer); }[/code]
這里作為示例,提供了兩個實現,一個基於MySql資料庫,一個基於Oracle,對這里的簡單示例而言,基於Oracle和MySql的實現並沒有什麼太大區別,只是為了說明系統設計的結構。
作為最常用的創建模式,Factory模式在這里起到來接介面和實現的橋梁作用。通過Factory模式,我們可以根據具體需要載入相應得實現,並將此實現作為所對應介面的一個實例提供給業務層使用:
[code]CustomerDAO custDAO =(CustomerDAO)DAOFactory.getDAO(CustomerDAO.class); Customer customer = custDAO.getCustomer(customerID);[/code]
通過上面的代碼我們可以看到,通過介面我們將具體的DAO實現從代碼中分離。
也就是說,業務層通過介面調用底層實現,具體的DAO實現類不會出現在我們的業務代碼中。而具體實現類在配置文件中加以配置,之後DAOFactory.getDAO方法通過讀取配置文件獲得當前我們期望使用的視線類的類名,再通過Java Class動態載入機制載入後返回。
從而我們的代碼並不依賴於某個特定的實現類,只需要在部署的時候在配置文件中指定當前採用的實現類即可。
本例中,為了提高性能,避免每次調用都讀取配置文件所引起的大量磁碟操作,採用了HashMap作為DAO緩存實現示例:
[code]package net.wanjin.lab.persistence.; import java.util.HashMap; public class DAOFactory { private static HashMap Map = null; /** * Return a implemetation instance of the specified DAO Interface * @return the DAO Implemmenation Class Instance */ public static Object getDAO(Class Interface){ initial(); Object = Map.get(Interface); if(null ==){ throw new DAOException("No Implementation found of DAO interface =>" +Interface.getName()); } return ; } /** * Initial the DAOFactory * Load DAO Interface and Implementation In Map for later use */ public static synchronized void initial(){ if(null==Map){ Map =DAOConfig.load();//根據配置文件載入DAO實現配置 } } }[/code]
[code]package net.wanjin.lab.persistence.; import java.util.Enumeration; import java.util.HashMap; import java.util.Properties; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; /** * DAOConfig 類實現了配置文件的讀取功能,並根據配置文件中的內容載入制定的介面和實現類; * @author Administrator */ public class DAOConfig { private static Logger logger = LogManager.getLogger(DAOConfig.class); private static final String DAO_CONFIG_FILE=".xml"; private static final String DAO_CONFIG_SECTION="DAO"; /** * Load the DAO Interface_Implementation into a HashMap * @return */ public static synchronized HashMap load(){ HashMap map = new HashMap(); JFigLocator jfigLocator = new JFigLocator(DAO_CONFIG_FILE); JFigIF Config = JFig.getInstance(jfigLocator); Properties prop = Config.getSectionAsProperties(DAO_CONFIG_SECTION); Enumeration enumSection = prop.keys(); while(enumSection.hasMoreElements()){ String Iface =(String)enumSection.nextElement(); String Impl = prop.getProperty(Iface); try{ Class iface = ClassToolKit.loadClass(Iface); Class impl = ClassToolKit.loadClass(Impl); //將介面作為HashMap索引,實現類作為值 map.put(iface, impl); }catch(ClassNotFoundException e){ logger.debug("No Class Found"+e); } }//while enumSection return map; } }[/code[code]]//.xml 文件 <?xml version="1.0" encoding="UTF-8"?> <configuration> <section > <entry key="net.wanjin.lab.persistence..iface.CustomerDAO" value="net.wanjin.lab.persistence..impl.CustomerDAOImp_Mysql"/> <entry key="net.wanjin.lab.persistence..iface.PromotionDAO" value="net.wanjin.lab.persistence..impl.PromotionDAOImp_Mysql"/> </section> </configuration>[/code]
⑵ DAO屬於一個設計模式嗎
DAO是Data Access Object數據訪問介面,數據訪問:故名思義就是與資料庫打交道。夾在業務邏輯與資料庫資源中間。
DAO的功能:
1. DAO用來封裝Data Source的..就比如,Connection conn = DAOFacotry.createConnection()..
就可以把Driver. URL. username, passpword這一些放在DAO中
以後要更改資料庫的類型.比如要把MSSQL換成Oracle的話..只需要更改DAOFacory裡面的getConnection()裡面的Driver.URL.之類的..
2. DAO也是把對資料庫的操作(比如最基本的CRUD操作)全部封裝在裡面..
比如說你要你要插入一個新的用戶..那麼.在DAO中我們只需要提供一個insertUser(User user)這一個方法就可以了..具體的操作是在DAO中實現的...
那麼對於要調用DAO的時候.我們只要知道insertUser(User)是用來插入一個新的用戶...而不需要知道是如何實現的。
一般 DAO是與Abstract Factory模式一起來用的
⑶ 100分求基於DAO模式的UML設計實例
你先明白啥叫DAO,DAO不是模式
⑷ 在DAO中如何體現DAO設計模式
介面編程
⑸ DAO國際設計機構大家了解嗎做過什麼項目
項目,包括:中國金融信息大廈、中國跨國采購會展中心、上海金山政府會議中心、廣州大亞灣翡翠山城大酒店、上海浦東新區金橋商業中心、鄭州亞新商務中心辦公樓、上海旭輝國際虹橋商務中心辦公樓、上海張江總部基地辦公樓、重慶涪陵李渡新城、成都錦江198世界現代田園城市規劃等。
DAO國際設計機構,是由美國斯道沃STOA建築規劃(中國)有限公司、上海陸道工程設計管理有限公司共同組建,為客戶提供的多元化專業設計和管理的機構。在境外,設有包括休斯頓在內的6家分公司。在國內,除上海外,已設有成都、鄭州分公司,並擬在武漢等城市增設分公司和辦事處。
DAO國際設計機構擁有國際技術、人才和行業背景以及國家建設部批準的建築工程設計綜合甲級、城市規劃乙級、市政工程乙級資質。2004年起,就致力於為客戶提供全程一體化的綜合解決方案。
發展至今,DAO國際設計機構已擁有一支近200名、由境內、外的建築師、規劃師、工程師、建築管理專家組成的設計團隊以及各類專業顧問團隊。與美國第三大結構技術公司Desimone建立了長期戰略合作關系。並致力於採用全程「BIM」技術為客戶提供更優質的專業服務。
DAO國際設計機構提供策劃研發、規劃設計、建築設計、市政設計、景觀設計、室內設計、工程咨詢、項目管理等建築業綜合服務。緊密的專業配合、國際的技術能力結合國內的資質背景,能為客戶提供更全面、技術性更強的服務。機構承接過許多規模龐大、復雜度高的項目,先後與諸多知名地產開發企業、跨國公司和政府部門建立了長期的戰略合作關系。服務的項目覆蓋國內二十幾個省份和四個直轄市。
DAO國際設計機構還長期專注城市可持續發展的研究。自2011年起,與中國低碳行動聯盟合作成立「中國低碳城市設計研究院」,並成為「中國低碳行動聯盟」指定設計單位。
⑹ 在DAO中如何體現DAO設計模式
sessionfactory!
⑺ java 中 層怎麼設計
package ;
import java.util.List;
import vo.*;
public interface IUsersDAO {
//按姓名查詢
public List<Users> findUsersByName(String uname) throws Exception;
//查詢所有用戶
public List<Users> findAllUsers() throws Exception;
//按id查詢
public Users findUsersById(int id)throws Exception;
//修改操作
public boolean UsersUpdate(Users usr)throws Exception;
//增加操作
//public boolean doInsert(Person per)throws Exception;
//修改操作
//public boolean doUpdate(Person per)throws Exception;
//刪除操作
//public boolean doDelete(int id)throws Exception;
//按id查詢
//public Person findById(int id)throws Exception;
//查詢全部
//public List<Proct> findAllProct() throws Exception;
//模糊查詢
//public List<Proct> findByLike(String cond)throws Exception;
}
⑻ 軟體設計:DAO層該如何設計
黔 新華為你解答:
關於Dao層的設計我現在也還是有點模糊,大大小小的項目也做了五六個了,負責的資料庫設計也有三四個了。
在對Dao層進行設計時採用過兩種方案:
方案一:每一表對應一個Dao類(介面也可),每個Dao將完成對該表的增刪改查以及業務上要求的查詢操作。這么設計的話如果表很多的話將會產生很多類,並且將會出現大量重復的代碼,因為每一個Dao中都將涉及到基礎的增刪改查。
方案二:寫一個基礎的類,可以完成基本的增刪改查,其他的對於業務上有額外需求的表單獨在寫一個類,不過這個類只包括額外的功能。這里的基礎類寫的時候是需要嚴格注意的,因為採用的類似映射的實現,需要你把實體類設計的同表結構一摸一樣,因為在該類中對資料庫的增刪改查的Sql語句就是通過對實體類類名以及對實體類類中屬性的提取完形成的。
這里給出一個基本的添加方法(vb.net實現):
Public Class SqlDao : Implements Dal.IDao
Private SqlDr As SqlDataReader
Private SqlCon As SqlConnection
Private SqlCmd As SqlCommand
'從配置文件app.config中取得連接資料庫的字元串
Private strConnect As String = ConfigurationManager.AppSettings("strCon")
'得到類名
Private strClassName As String
'得到類的類型
Private mType As Type
'得到屬性集
Private mProS As PropertyInfo()
'在初始化方法中連接資料庫
'Public Sub Init(ByVal obj As Object) Implements IDao.Init
' SqlCon = New SqlConnection(strConnect)
' '在構造函數中對必要類型進行初始化
' strClassName = TypeName(obj)
' mType = obj.GetType()
' mProS = mType.GetProperties
'End Sub
'連接資料庫的一個私有方法
Private Function GetCon() As SqlConnection Implements IDao.GetCon
Try
If (SqlCon.State = ConnectionState.Closed) Then
SqlCon.Open()
End If
Catch ex As Exception
MsgBox("打開資料庫時:" + ex.Message)
End Try
Return SqlCon
End Function
''' <summary>
''' 將對象添加到對應的表中,參數為對象,返回值為Int型,表示影響的行數
''' </summary>
''' <param name="Entity "></param>
''' <returns>Integer</returns>
''' <remarks></remarks>
Public Function AddObj(Of T)(ByVal Entity As T) As Integer Implements IDao.AddObj
Dim res As Integer = 0 '用來返回該操作影響的行數
'定義單個屬性
Dim mPro As PropertyInfo
'定義sql參數
Dim para As SqlParameter
Dim strFields As String = ""
Dim strCondition As String = ""
Dim strSql As String = ""
For Each mPro In mProS
'該循環用來進行參數組合
'再添加時不用添加時間
strFields = CStr(Trim(mPro.GetValue(Entity, Nothing))) '獲取屬性值
If strFields <> "0" And strFields <> "00:00:00" And strFields <> "" Then
strSql = strSql + "@" + mPro.Name + ","
'組合形成欄位名
strCondition = strCondition + mPro.Name + ","
End If
Next
'最後再插入最後的括弧
strSql = Left(strSql, Len(strSql) - 1) + ")"
strCondition = Left(strCondition, Len(strCondition) - 1) + ")"
strSql = "INSERT INTO " + strClassName + " (" + strCondition + " VALUES (" + strSql
'MsgBox(strSql)
Try
Using sCmd As New SqlCommand(strSql, GetCon)
'設定執行方式
sCmd.CommandType = CommandType.Text
For Each mPro In mProS
'進行參數的賦值
'Dim stra As String = mPro.GetValue(obj, Nothing)
'一般的添加不用加入時間,除了下機表
strFields = CStr(Trim(mPro.GetValue(Entity, Nothing))) '獲取屬性值
If strFields <> "0" And strFields <> "00:00:00" And strFields <> "" Then
para = New SqlParameter("@" + mPro.Name, mPro.GetValue(Entity, Nothing))
sCmd.Parameters.Add(para)
End If
Next
res = sCmd.ExecuteNonQuery
End Using
Catch ex As Exception
MsgBox("進行對象添加時:" + ex.Message)
End Try
Return res '返回該操作影響的行數
End Function
End Class
這幾天從網上也查了一些資料主要就是關於Dao層該如何設計的問題,最直接的設計方案就是每一個表對應一個Dao,說是代碼重復太多,不過這樣設計那些基本的代碼是不用寫的,都有現成的工具,直接根據表生成對應的增刪改查。
不過因為需要重復的代碼太多了,因此有人提出這種方法:
public interface BaseDao<T> {
public void create (T t);
public void delete (T t);
public void update (T t);
}
public interface WindDao extends BaseDao<Wind> {
public void other (Wind wind);
}
將基本的增刪改查通過泛型放置到一個基礎的介面中,其他的只需實現該介面,如果有額外的需求便可自行添加方法。這可謂一個典型的繼承的應用。不過說實話,這種方法也不能使代碼量減少。
⑼ 在DAO中如何體現DAO設計模式
把對象的基本CRUD操作封裝到一個DAO中就是這種設計模式
⑽ 求教java高手:什麼是DAO設計模式,聽老師說DAO設計模式通常會和工廠設計模式、代理設計模式一起使用,
class User {
private String name;
private int age;
public void setName(String name){
this.name=name;
}
public void setAge(int age){
this.age=age;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
}
interface UserDAO {
public boolean doCreate(User user)throws Exception;
}
class UserDAOImpl implements UserDAO {
private String str=null;
public UserDAOImpl(String str){
this.str=str;
}
public boolean doCreate(User user)throws Exception{
boolean flag=false;
try{
System.out.println("真實主題類的資料庫增加操作");
}catch(Exception e){
e.printStackTrace();
}finally{
}
return flag;
}
}
class UserDAOProxy implements UserDAO {
private UserDAOImpl =null;
private String str=null; //此處其實應該傳入一個資料庫的連接到真實主題類的,不過這里只是個演示,所有以字元串的形式傳了進去
public UserDAOProxy(){
this.str=new String();
this.=new UserDAOImpl(this.str);
}
public boolean doCreate(User user)throws Exception{
boolean flag=true;
System.out.println("代理類的操作,打開資料庫,同時取得真實主題類的實例去調用真實的數據層操作");
try{
this..doCreate(user);
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println("代理類的操作,調用完真實主題類的操作,同時關閉資料庫");
}
return flag;
}
}
class UserDAOFactory {
public static UserDAO getUserDAONewInstance(){
System.out.println("通過工廠類取得代理類的實例去調用代理類的操作。");
return new UserDAOProxy();
}
}
public class FactoryDemo {
public static void main(String args[])throws Exception{
User user=new User();
user.setName("jhjjs");
user.setAge(20);
UserDAOFactory.getUserDAONewInstance().doCreate(user);
}
}
lz看下吧,剛做的