基本介紹
- 中文名:資料庫訪問對象
- 外文名:Data Access Object
- 簡稱:DAO
- 局限性:適用於單系統應用程式
訪問接口,訪問對象,寫盤方式,相關信息,
訪問接口
DAO(Data Access Object)是一個數據訪問接口,數據訪問:顧名思義就是與資料庫打交道。夾在業務邏輯與資料庫資源中間。
在核心J2EE模式中是這樣介紹DAO模式的:為了建立一個健壯的J2EE套用,應該將所有對數據源的訪問操作抽象封裝在一個公共API中。用程式設計的語言來說,就是建立一個接口,接口中定義了此應用程式中將會用到的所有事務方法。在這個應用程式中,當需要和數據源進行互動的時候則使用這個接口,並且編寫一個單獨的類來實現這個接口在邏輯上對應這個特定的數據存儲。
訪問對象
DAO(數據訪問對象)是一種應用程式編程接口(API),存在於微軟的Visual Basic中,它允許程式設計師請求對微軟的Access資料庫的訪問。DAO是微軟的第一個面向對象的資料庫接口。DAO對象封閉了Access的Jet函式。通過Jet函式,它還可以訪問其他的結構化查詢語言(SQL)資料庫。
J2EE開發人員使用數據訪問對象(DAO)設計模式把底層的數據訪問邏輯和高層的業務邏輯分開.實現DAO模式能夠更加專注於編寫數據訪問代碼.
我們先來回顧一下DAO設計模式和數據訪問對象.
DAO基礎
DAO模式是標準的J2EE設計模式之一.開發人員使用這個模式把底層的數據訪問操作和上層的商務邏輯分開.一個典型的DAO實現有下列幾個組件:
1. 一個DAO工廠類;
2. 一個DAO接口;
3. 一個實現DAO接口的具體類;
4. 數據傳遞對象(有些時候叫做值對象).
具體的DAO類包含了從特定的數據源訪問數據的邏輯。在下面的這段中你將學到設計和實現數據訪問對象的技術。
事務劃分:
關於DAO要記住的一件重要事情是它們是事務性對象。每個被DAO執行的操作(對象創建,更新、或刪除數據)都是和事務相關聯的。同樣的,事務劃分(transaction demarcation)的概念是特別重要的。
事務劃分是在事務界定定義中的方式。J2EE規範為事務劃分描述了兩種模式:編程性事務(programmatic)和聲明性事務(declarative).下表是對這兩種模式的拆分:
聲明性事務劃分 編程性事務劃分
程式設計師使用EJB的部署描述符聲明事務屬性 程式設計師擔負編寫事務邏輯代碼的責任。
運行時環境(EJB容器)使用這些屬性來自動的管理事務。應用程式通過一個API接口來控制事務。
寫盤方式
這種寫入模式主要用於光碟的複製,一次完成整張光碟的刻錄。其特點是能使複製出來的光碟與源盤毫無二致。DAO寫入方式可以輕鬆完成對於音樂CD、混合或特殊類型CD-ROM等數據軌之間存在間隙的光碟的複製,且可以確保數據結構與間隙長度都完全相同。值得一提的是,由於DAO寫入方式把整張光碟當作一個區段來處理,一些小的失誤都有可能導致整張光碟徹底報廢,所以它對數據傳送的穩定性和驅動器的性能有較高的要求。
相關信息
一、數據訪問對象DAO的結構
上一章我們知道了DAO是什麼,它可以乾什麼,以及簡單的了解了它是如何實現這一功能,這一章我們講逐步學習DAO的結構。在將講這一章之前,首先講兩個題外話:
大家對面向對象編程一定不陌生,但究竟什麼是面向對象編程,很多人一下子也說不出個所以然來;在VB的DAO中又是如何體現面向對象的呢,恐怕即便是使用了一段VB的網友也很難說清。這也難怪,VB本身並不是個完全的面向對象的編程環境,它的很多如動態數組等就不是面向對象的,但在DAO中是完全的面向對象的。其實面向對象的最初思想就是將數據和操作封裝在一起,形成對象,而在DAO中正是體現了這一點,它將數據的值作為屬性,數據的查詢作為方法,數據值的變化作為事件,完全封裝在DAO對象中,希望諸位盟友在使用中注意,逐步領悟面向對象的編程方法。
資料庫前端開發系統和後台系統
經常由朋友說他會DELPHI,會PB,實際上用前端和後台的概念來看,他們都只是會一種前端開發工具而已,嚴格說起來並不能算會資料庫的開發。人們往往只看到前台套用的功能而忽視了後台系統的套用,或者認為這兩者根本就是一回事。前端後台概念用在單機上,就是VB與Access,用在網路中就是VB與SQLSever,只會VB或DELPHI是不能稱為掌握資料庫編程的,而且在編程中,要善於利用後台資料庫提供功能,這樣的程式運行起來更快,程式更精練。
題外話講完,現在切入正題。DAO的結構如圖所示:
以上是DAO整體結構圖,下面將分章節逐步講述每個對象的使用
二、數據訪問對象DAO的功能
1. DAO用來封裝Data Source的..就比如,Connection conn = DAOFactory.createConnection()..
就可以把Driver. URL. username,passpword這一些放在DAO中
以後要更改資料庫的類型.比如要把MYSQL換成Oracle的話..只需要更改DAOFactory裡面的getConnection()裡面的Driver.URL.之類的..
2. DAO也是把對資料庫的操作(比如最基本的CRUD操作)全部封裝在裡面..
比如說你要插入一個新的用戶..那么.在DAO中我們只需要提供一個insertUser(User user)這一個方法就可以了..具體的操作是在DAO中實現的...
那么對於要調用DAO的時候.我們只要知道insertUser(User)是用來插入一個新的用戶...而不需要知道是如何實現的..
一般 DAO是與Abstract Factory模式一起來用的...
Factory來建立資料庫和定位具體的DAO(比如說是UserDao..CustomerDao..)..一般將getConnection設定為static..也可以把HibernateSessionFactory這一個公共類放在這一AbstractFactory類中去...
public class DAOFactory {
private static final SessionFactory sessionFactory;
// 定義一個ThreadLocal .
static Session currentSession().....
public UserDao getUserDAO() { return new UserDaoImpl(sesssion);}
pulbic OtherDao getOtherDAO() { return new OtherDaoImpl(session);}
......
}
public interface UserDao {
public insertUser(FormBean)
public updateUser(FormBean);
}
然後就實現DAO的接口: (Struts的FormBean...VO來的..)
publicclassUserDaoImpl implements UserDao {
privateSession session;
public UserDaoImpl(Session session){
this.session = session;
}...
public insertUser(FormBean) {
..//..
session.save(UserPO);
..//..
return FormBean;
}
public FormBean updateUser(FormBean) {
..//..
session.update(UserPO);
..//..
return FormBean;
}
}
最後定義你的PO:
publicclassUserPO {
String firstname,lastname,password..........
}
Huhmmmm..........
三、實戰套用——使用數據訪問對象DAO
1 概述
Visual C++提供了對DAO的封裝,MFC DAO類封裝了DAO(資料庫訪問對象)的大部分功能,從而Visual C++程式就可以使用Visual C++提供的MFC DAO類方便的訪問Microsoft Jet 資料庫,編制簡潔、有Visaul C++特色的資料庫應用程式。
資料庫訪問對象(DAO)提供了一種通過程式代碼創建和操縱資料庫的機制。多個DAO對象構成一個體系結構,在這個結構里,各個DAO對象協同工作。DAO支持以下四個資料庫選項:
打開訪問資料庫(MDB檔案)——MDB檔案是一個自包含的資料庫,它包括查詢定義、安全信??須指定MDB檔案的路徑名。
用Jet引擎找開ISAM型(索引順序訪問方法)數據源(包括dBase,FoxPro,Paradox,Btrieve,Excel或文本檔案)——即使已經設定了ODBC數據源,要用Jet引擎來訪問這些檔案類型中的一種,也必須以ISAM型數據源的方式來找開檔案,而不是以ODBC數據源的方式。
給ACCESS資料庫附加外部表——這實際上是用DAO訪問ODBC數據源的首選方法。首先使用ACCESS把ODBC表添加到一個MDB檔案上,然後依照第一選項中介紹的方法用DAO找開這個MDB檔案就可以了。用戶也可以用ACCESS把IASM檔案附加到一個MDB檔案上。
2 套用DAO編程
2.1 打開資料庫
CDaoWorkspace對象代表一個DAO Workspace對象,在MFC DAO體系結構中處於最高處,定義了一個用戶的同資料庫的會話,並包含打開的資料庫,負責完成資料庫的事務處理。我們可以使用隱含的workspace對象。
CDaoDatabase對象代表了一個到資料庫的連線,在MFC中,是通過CDaoDatabase封裝的。
在構造CDaoDatabase對象時,有如下兩種方法:
創建一個CDaoDatabase對象,並向其傳遞一個指向一個已經找開的CdaoWorkspace對象的指針。
創建一個CDaoDatabase對象,而不明確地指定使用的workspace,此時,MFC將創建一個新的臨時的CDaoWorkspace對象。
如下代碼所示:
CDaoDatabasedb;
db.Open(“test.mdb”,FALSE,FALSE,_T(“”);
其中參數一包括要打開的檔案的全路徑名。
2.2 查詢記錄
一個DAO recordset對象,代表一個數據記錄的集合,該集合是一個庫表或者是一個查詢的運行結果中的全部記錄。CDaoRecorset對象有三種類型:表、動態集、快照。
通常情況下,我們在應用程式中可以使用CDaoRecordset的導出類,這一般是通過ClassWizard或AppWizard來生成的。但我們也可以直接使用CDaoRecordset類生成的對象。此時,我們可以動態地綁定recordset對象的數據成員。
如下代碼所示:
COleVariant var;
long id;
CString str;
CDaoRecordset m_Set(&db);
m_Set.Open(“查詢的SQL語句”);
while(!m_Set.IsEOF())
{
/*
處理
m_Set.GetFieldValue(“ID”,var);
id=V_I4(var);
m_Set.GetFieldValue(“Name”,var);
str=var.pbVal;
*/
m_Set.MoveNext();
}
m_Set.Close();
2.3 添加記錄
添加記錄用AddNew函式,此時用SetFieldValue來進行賦值。
如下代碼所示:
m_pDaoRecordset->AddNew ();
sprintf(strValue,"%s",>m_UserName );
m_pDaoRecordset->SetFieldValue ("UserName",strValue);
sprintf(strValue,"%d",m_PointId );
m_pDaoRecordset->SetFieldValue ("PointId",strValue);
dataSrc.SetDateTime (m_UpdateTime .GetYear ),m_UpdateTime .GetMonth ),m_UpdateTime .GetDay (),
m_UpdateTime .GetHour (),m_UpdateTime .GetMinute (),m_UpdateTime .GetSecond ());
valValue=dataSrc;
m_pDaoRecordset->SetFieldValue ("UpdateTime",valValue);
sprintf(strValue,"%f",m_pRecordset->m_OldValue );
m_pDaoRecordset->SetFieldValue ("OldValue",strValue);
sprintf(strValue,"%f",m_pRecordset->m_NewValue );
m_pDaoRecordset->SetFieldValue ("NewValue",strValue);
m_pDaoRecordset->Update ();
此時,要注意,日期時間型數據要用SetDataTime函式來賦值,這裡面要用到COleVariant類型數據,具體用法可以參考有關幫助。
2.4 修改記錄
修改記錄用Edit()函式,把記錄定位到要修改的位置,調用Edit函式,修改完成後,調用Update函式。
如下代碼所示:
m_Set.Edit();
m_Set.SetFieldValue(“列名”,”字元串”);
m_Set.Update();
2.5 刪除記錄
刪除記錄用Delete()函式,使用後不需調用Update()函式。
2.6 統計記錄
可以使用如下代碼來統計記錄數:
COleVariant varValue;
CDaoRecordset m_Set(&db);
m_Set.Open(dbOpenDynaset,”SQL語句”);
varValue=m_Set.GetFieldValue(0);
m_lMaxCount=V_I4(&varValue);
m_Set.Close();
如果是統計一張表中總記錄,可以使用CDaoTableDef對象,如下代碼所示:
CDaoTableDefm_Set(&gUseDB);
Count=m_Set.GetRecordCount();
m_Set.Close();
不能用CDaoRecordset對象的GetRecordCount()來取得記錄數。
3 總結