在核心J2EE模式中是這樣介紹DAO模式的:為了建立一個健壯的J2EE應用,應該將所有對數據源的訪問操作抽象封裝在一個公共API中。用程序設計的語言來說,就是建立一個接口,接口中定義了此應用程序中將會用到的所有事務方法。在這個應用程序中,當需要和數據源進行交互的時候則使用這個接口,並且編寫一個單獨的類來實現這個接口在邏輯上對應這個特定的數據存儲。<?XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" />
比如考慮在iBatis: SQL Maps中的應用例子。這是一個Struts應用答應對一個關系表執行SELECT, INSERT, UPDATE和DELETE的SQL請求。在這個應用中,使用SQL Maps做持續性框架。現在我們要修改這個應用,將這個關系表儲存在一個XML文件中而不是存在關系數據庫中,或者使用Hibernate來實現SELECT請求,而用SQL Map來執行其他請求,因為Hibernate提供了對高速緩存更好的支持。這樣的修改很難實現,或者即使我們能修改而實現了這個功能,也會是很混亂的解決方案。
對於這類問題更好的解決方法是建立一個ContactDAO接口,在這個接口中定義處理SELECT, INSERT, UPDATE, 和DELETE 請求的事務方法。然後根據不同的事務邏輯建立不同的類實現各個方法。所以可能會有一個類處理使用SQL Maps同關系表進行交互的情況,而另外一個類處理用XML文件存放關系表而不是關系數據庫的情況,等等。在項目中,根據實際的需要從不同的ContactDAO中選擇相應的實現。這種關系見圖1:
圖1. ContactDAO 接口及實現
iBatis DAO是由Apache主持的開源框架項目,主要目標是為了解決這類問題。它答應在工程中以DAO模式為基礎建立應用。這就意味著可以建立一個XML文件,並聲明XMLContactDAO.Java是ContactDAO的實現類,這個類知道如何從XML文件中讀寫數據。SQLMapContactDAO則知道如何用SQL Maps作為持續化框架與關系表進行交互。在工程中,假如向DAO框架提交一個需要XML的ContactDAO請求,框架則會返回一個XMLContactDAO對象。同樣的DAO框架提供了唯一的接口處理事務治理,這個接口能實現與數據的存儲方式無關。它同樣考慮了底層連接治理細節和初始化存儲框架。
這篇文章是關於如何一步一步的在項目中應用iBatis DAO框架的基礎指導。我們將由如何把SQL Maps一文中的應用實例改為應用DAO框架入手。然後,我們要討論DAO框架的構造。再下一步,我們關注事務治理是如何在DAO框架中得到支持的。最後一部分是關於如何建立自己的事務治理模塊。
示例應用
首先,我們將SQL Maps一文中的例子改為應用DAO框架。
1. 將ibatis-dao-2.jar文件復制到WEB-INF/lib目錄下。
2. 在Java源程序的目錄裡新建一個如下的DAOMap.xml文件
清單1:
"com.sample.contact.dao.sqlmap.SQLMapContactDAO"/>
DAOMap.xml是發布iBatis DAO框架的配置文件。
3. 建立ContactDAO.java,如下:
單2:
public interface ContactDAO extends DAO {
public int insertContact(Contact contact);
public int updateContact(Contact contact);
public Contact selectContact(int contactId);
public int deleteContact(int contactId);
}
ContactDAO.java定義了用戶和一個關系表進行交互所需要用到的所有事務處理方法。請注重到ContactDAO.java中的所有方法都將一個Contact對象作為參數,這是一個用來攜帶數據的數據傳遞對象。
4. 建立一個SQLMapContactDAO.java文件,如下
清單3:
public class SQLMapContactDAO extends
SqlMapDaoTemplate implements ContactDAO {
public SQLMapContactDAO(DaoManager arg0) {
super(arg0);
}
public int deleteContact(int contactId) {
return super.delete("deleteContact",
new Integer(contactId));
}
public int insertContact(Contact contact) {
Integer contactId =(Integer)super.insert
("insertContact",contact);
return contact.getContactId();
}
public Contact selectContact(int contactId) {
return (Contact)super.queryForObject("getContact",
new Integer(contactId));
}
public int updateContact(Contact contact) {
return super.update("updateContact",contact);
}
}
SQLMapContactDAO是ContactDAO接口的具體實現,它用SQL Maps作為存儲治理機制。注重到我們並沒有寫任何代碼來或者初始化SQL Maps,或得到一個連接,或者在類中標注一個事務的界限。相反,我們繼續SqlMapDaoTemplate.java類,它幫我們處理下層的、反復的操作。我們在SQLMapContactDAO類中需要考慮的唯一的事情就是事務處理邏輯。
5. 修改ContactSelectAction.java類中的execute()方法,如下:
清單4:
Contact contactForm = (Contact) form;
Reader reader=
Resources.getResourceAsReader("DAOMap.xml");
DaoManager daoManager =
DaoManagerBuilder.buildDaoManager(reader);
ContactDAO contactDAO =
(ContactDAO) daoManager.getDao(
ContactDAO.class,"sqlmap");
request.setAttribute("contactDetail",
contactDAO.selectContact(
contactForm.getContactId()));
最後一步是修改ContactSelectAction類中的execute()方法,使它使用DAO框架。為了初始化DAO框架,我們需要一個為DAOMap.xml 預備一個Reader對象。iBatis框架為我們提供了方法Resources.getResourceAsReader()來讀取資源。一旦有了Reader對象來讀取DAOMap.xml,就能將它們讀取至DAOManagerBuilder.buildDaoManager(),返回一個DaoManager實例,將來用於與DAO框架進行交互。從理論上來說,應該在項目啟動的時候初始化DAO框架,在我們這個程序中,可以將這個模塊放入Struts插件中,但是為了簡化這個例子,我們將初始化模塊放入execute方法中。
有了DaoManager實例後,可以調用相應的接口和存儲實現類(在