熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

《J2EE核心模式》(DAO模式)

2013-11-23 19:41:09  來源: Java高級技術 

  很多的JEE應用程序需要使用持久性數據(數據庫文件等)不同的程序持久性存儲是各不相同的並且用來訪問這些不同的持久性存儲機制的API也有很大的不同如果應用程序要在不同的持久性存儲間遷移這些訪問特定持久存儲層的代碼將面臨重寫
  
  如何解決這個問題?且看DAO模式
  
  數據訪問對象(Data Acess Object) 模式
  
  環境
  根據數據源不同數據訪問也不同根據存儲的類型(關系數據庫面向對象數據庫文件等等)和供應商實現不同持久性存儲(比如數據庫)的訪問差別也很大
  
  問題
  許多真是的JEE應用程序需要在一定程度上使用持久性數據對於許多應用程序持久性存儲是使用不同的機制實現的並且用來訪問這些不同的持久性存儲機制的API也有很大的不同
  比如應用程序使用實體bean(這裡應該是指BMP的beanCMP的bean已大大降低了與RDBMS的耦合)的分布式組件來表示持久性數據或者使用JDBC API來訪問駐留在某關系數據庫管理系統(RDBMS)中的數據這些組件中包含連接性性和數據訪問代碼會引入這些組件與數據源實現之間的緊密耦合組件中這類代碼依賴性使應用程序從某種數據源遷移到其他種類的數據源將變得非常麻煩和困難當數據源變化時組件也需要改變以便於能夠處理新類型的數據源
  
  (舉個例子來說我們UPTEL系統是使用JDBC API對 ORACLE數據庫進行連接和數據訪問的這些JDBC API與SQL語句散布在系統中當我們需要將UPTEL遷移到其他RDBMS時比如曾經遷移到INFORMIX就面臨重寫數據庫連接和訪問數據的模塊)
  
  作用力
  諸如bean管理的實體bean會話beanservlet等組件往往需要從持久性存儲數據源中檢索數據以及進行數據存儲等操作
  根據產品供應商的不同持久性存儲API差別也很大這些API和其能力同樣根據存儲的類型不同也有差別這樣存在以下缺點即訪問這些獨立系統的API很不統一
  組件需要透明於實際的持久性存儲或者數據源實現以便於提供到不同供應商產品不同存儲類型和不同數據源類型的更容易的移植性
  
  解決方案
  使用數據訪問對象(DAO)模式來抽象和封裝所有對數據源的訪問DAO管理著與數據源的連接以便檢索和存儲數據
  DAO實現了用來操作數據源的訪問機制數據源可以時RDBMSLDAPFile等依賴於DAO的業務組件為其客戶端使用DAO提供更簡單的接口DAO完全向客戶端隱藏了數據源實現細節由於當低層數據源實現變化時DAO向客戶端提供的接口不會變化所有該模式允許DAO調整到不同的存儲模式而不會影響其客戶端或者業務組件重要的是DAO充當組件和數據源之間的適配器
  
  (按照這個理論如果我們UPTEL系統使用了DAO模式就可以無縫的從ORACLE遷移到任何一個RDBMS了夢想總是很完美的且看看DAO模式如何實現)
  
  結構是表示DAO模式中各種關系的類圖
  
  此主題相關圖片如下
  
 

  參與者和職責
  )BusinessObject(業務對象)
  代表數據客戶端正是該對象需要訪問數據源以獲取和存儲數據
  )DataAccessObject(數據訪問對象)
  是該模式的主要對象DataAccessObject抽取該BusinessObject的低層數據訪問實現以保證對數據源的透明訪問BusinessObject也可以把數據加載和存儲操作委托給DataAccessObject
  )DataSource(數據源)
  代表數據源實現數據源可以是各RDBMSR數據庫OODBMSXML文件等等
  )valueObject(值對象)
  代表用做數據攜帶著的值對象DataAccessObject可以使用值對象來把數據返回給客戶端
  DataAccessObject也許會接受來自於客戶端的數據其中這些用於更新數據源的數據存放於值對象中來傳遞
  
  策略
  )自動DAO代碼產生策略
  因為每個BusinessObject對應於一個特殊的DAO因此有可能建立BusinessObjectDAO和低層實現(比如RDBMS中的表)之間的關系(映射)一點這些關系(映射)已經建立我們就可以編寫與應用程序有館的代碼生成的簡單工具了(什麼?自己寫GP程序?用ORM的附帶工具自動生成不就完了最多自己寫幾個Adapter牛人就是不同啥都要自己寫)其中的工具可以產生該應用程序需要的所有DAO代碼
  如果DAO需求很復雜我們可以采用第三方工具其中這些工具提供對象到RDBMS數據庫的關系映射(這裡指的是前面提到的ORM工具全稱是Object Relation Mapping目前成熟的ORM工具有很多:HibernateOJBTorqueTopLink等等)
  這些工具通常包含GUI工具來把業務對象映射到持久性存儲對象並且因而定義中間DAO一旦這些映射完成這些工具會自動地生成代碼並且也許會提供其他增值功能比如結果緩沖查詢緩沖與應用程序集成以及與其他第三方產品(比如分布式緩沖)地繼承等等
  (增值服務Torque提供了結果緩沖Hibernate提供了對Oracle數據庫SQL指令的優化OJB提供JDO APIOMDB API)
  
  )數據訪問對象的工廠策略
  通過調整抽象工廠和工廠方法模式DAO模式可以達到很高的靈活度
  當低層存儲不會隨著實現變化而變化時該策略可以使用工廠方法模式來實現該策略以產生應用程序需要的大量DAO是這種情況下的類圖
  
  此主題相關圖片如下
  
 

  當低層存儲隨著實現變化而變化時該策略可以使用抽象工廠方法模式而實現
  圖是這種情況下的類圖
  
  此主題相關圖片如下
  

  結果
  )啟用透明性
  業務對象可以是使用數據源而無須了解該數據源實現的具體細節訪問是透明的原因是實現被隱藏在DAO的內部
  )啟用更容易的遷移
  DAO層使應用程序更加容易地遷移到一個不同的數據庫實現業務對象不了解低層數據實現因而該遷移只涉及對DAO層的變化更進一步說如果使用工廠策略則有可能為每一個低層存儲實現提供一個具體工廠實現在這種情況下遷移到不同的遷移實現意味著給應用程序提供一個新的工廠實現
  )減少業務對象中代碼復雜度
  由於DAO管理所有的數據訪問復雜性它可以簡化業務對象和其他使用DAO的客戶端中的代碼所有與實現有關的代碼(比如sql語句)都被包含在DAO中而不是包含在業務對象中這樣做提高了代碼的可讀性已經代碼生產效率
  )把所有的數據訪問集中到一個獨立的層
  因為所有的數據訪問操作現在被委托給DAO所有單獨的數據訪問層可以被看作把數據訪問實現與應用程序中的其他代碼相隔離的這種集中化使應用程序更容易地維護和管理
  )不適用於容器管理的持久性
  由於EJB容器用容器管理的持久性(CMP)來管理實體bean該容器會自動地服務所有的持久性存儲訪問使用容器管理的實體bean的應用程序不需要DAO層因為該應用程序服務器透明地提供該功能然而當需要組合使用CMP和BMP時DAO仍舊有用處
  )添加其他層
  DAO會在數據客戶端和數據源之間創建其他的對象層其中該數據源需要被設計和實現以便於權衡該模式的好處但是選擇本方法也會帶來額外的開銷
  )需要類層次設計
  在使用工廠策略時我們需要設計和實現具體工廠的層次以及這些工廠產生的具體產品層次如果能夠確保這種靈活性則有必要考慮這種額外的工作這樣做會增加設計的復雜性然而在實現該工廠策略時你可以首先考慮工廠方法模式然後再根據需要過渡到抽象工廠
  
  范例代碼
  實現數據訪問對象模式
  范例時表示Customer信息的持久性對象的DAO范例代碼當findCustomer()被調用時CloudscapeCustomerDAO創建一個Customer值對象
  范例是使用DAO的范例代碼
  
  實現數據訪問對象的工廠策略
  )使用工廠方法模式
  )使用抽象工廠模式
  范例代碼是CloudscapeDAOFactory的范例代碼
  范例代碼中的CustomerDAO接口為Customer持久性對象定義了DAO方法這些接口是被所有具體DAO實現來實現的比如CloudscapeCustomerDAOOracleCustomerDAO已經SybaseCustomerDAOAccount和OrederDAO接口也與此類似
  
  Example Abstract DAOFactory Class
  
  // Abstract class DAO Factory
  public abstract class DAOFactory {
  
  // List of DAO types supported by the factory
  public static final int CLOUDSCAPE = ;
  public static final int ORACLE = ;
  public static final int SYBASE = ;
  
  
  // There will be a method for each DAO that can be
  // created The concrete factories will have to
  // implement these methods
  public abstract CustomerDAO getCustomerDAO();
  public abstract AccountDAO getAccountDAO();
  public abstract OrderDAO getOrderDAO();
  
  
  public static DAOFactory getDAOFactory(
  int whichFactory) {
  
  switch (whichFactory) {
  case CLOUDSCAPE:
  return new CloudscapeDAOFactory();
  case ORACLE :
  return new OracleDAOFactory();
  case SYBASE :
  return new SybaseDAOFactory();
  
  default :

From:http://tw.wingwit.com/Article/program/Java/gj/201311/27295.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.