亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

基于iBatis的通用持久層對象

2019-11-18 11:57:13
字體:
來源:轉載
供稿:網友

        ibatis介紹
  使用ibatis 提供的ORM機制,對業務邏輯實現人員而言,面對的是純粹的java對象, 這一層與通過Hibernate 實現ORM 而言基本一致,而對于具體的數據操作,Hibernate 會自動生成SQL 語句,而ibatis 則要求開發者編寫具體的SQL 語句。相對Hibernate等 “全自動”ORM機制而言,ibatis 以SQL開發的工作量和數據庫移植性上的讓步,為系統 設計提供了更大的自由空間。作為“全自動”ORM 實現的一種有益補充,ibatis 的出現顯 得別具意義。

版權聲明:任何獲得Matrix授權的網站,轉載時請務必保留以下作者信息和鏈接

 

作者:fellow99
原文:http://www.matrix.org.cn/resource/article/44/44410_iBatis.Html
要害字:iBatis;ORM

一、為什么要設計“通用”的東西
  在大多數時候,我們所需要的持久層對象(PO)大多都是一張表(or視圖)對應一個類。按照Hibernate的思想,就是拋開數據庫的束縛,把焦點集中到業務對象中。而很多自動化工具的確讓做到了通過表結構生成對應的對象,or通過對象自動生成表。對于小項目來說,一切都是簡單的;對于有規范設計的項目來說,PO的設計也不是一件困難的工作。但是對于那些業務變動頻繁的項目來說,改動PO可能成了一件很繁重的工作。試想一下,假設某個表需要增加一個字段:對于Hibernate(or iBaits),首先要改配置文件,然后PO,然后DAO(也許沒有),然后業務邏輯,然后JO,然后界面,etc,貫通了全部層次。
  恩,寫程序的都不喜歡這些重復勞動,但是做企業級應用的誰不是天天在這些工作中打滾。
  研究過iBaits以后,發現有些通用的方法可以解決,就是設計一個通用的持久層對象。

二、基于什么技術
  iBatis可以使用Map對象作為PO,Hibernate似乎也有相關的功能(我沒有細看,不確定)。
  iBatis執行一條指令的過程大概是這樣的:

基于iBatis的通用持久層對象

其中圈圈1、2、3描述了iBatis最重要的三個對象。

圈圈1:statement簡單來說就是存儲sql語句的配置信息,一個最簡單的statement:



    insert into PRODUCT (PRD_ID, PRD_DESCRipTION) values (1, “Shih Tzu”)


其中id屬性是這個statement的唯一標識,全局不能重復。

以上當然是最簡單的了,沒有參數也不需要返回值,但實際情況下基本都需要傳入參數,下面就是介紹參數。

圈圈2:參數對象主要分兩種類型:parameterMap、parameterClass和Inline Parameter。

  其中parameterMap是配置文件定義傳入參數表,如下:




    
        insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (?,?);
    


  而parameterClass是傳入參數對象(JavaBean),如下:


    insert into PRODUCT values (#id#, #description#, #price#)


  Inline Parameter則是強化版的parameterClass,如下:


    insert into PRODUCT (PRD_ID, PRD_DESCRIPTION)
        values (#id:NUMERIC:-999999#, #description:VARCHAR:NO_ENTRY#);


  其中第一種方法看著就復雜,實際是為了兼容老版本留下來的,所以parameterClass是我們最常用的方法。官方文檔對parameterClass介紹很具體,因為這是核心之一,具體請自己查閱。有3個特性說明一下:

  a. parameterClass對象可以傳入一個Map對象(or Map子類)。本來假如是傳入JavaBean,程序會通過get/set來分析取得參數;而Map是key-value結構的,那程序會直接通過key來分析取參數。

  b. 看以下語句:


    insert into PRODUCT values (#id#, #description#, #price#, #classify.id#)


  藍色部分#classify.id#翻譯過來實際是product.getClassify().getId(),classify是Product對象的一個子對象。

  c. 在模板sql語句中除了“#”以外,還有“$”,它們兩代表的意思當然不同了:


    select * from PRODUCT order by $preferredOrder$


  “#”在生成sql語句的過程中,會變成“?”,同時在參數表中增加一個參數;

  “$”則會直接替換成參數對象對應的值,例如上面的preferredOrder的值可能是“price”,則生成的sql語句就是:select * from PRODUCT order by price。

  *需要非凡說明的是傳入參數這一部分將會是后面正題“通用持久層對象”的核心,怎么個通用法,怎么設計模板sql語句,都是在這部分上。



圈圈3:結果對象跟參數對象差不多,也有兩種,resultMap和resultClass,如下:

  resultMap就是配置文件中預定義了要取得的字段:


    
    


    select * from PRODUCT


  resultClass則是通過分析返回的字段,來填充結果對象:


    SELECT PER_ID as id, PER_FIRST_NAME as firstName
        FROM PERSON WHERE PER_ID = #value#


  跟參數對象相反,結果對象一般使用resultMap形式。引用官方的話:使用resultClass的自動映射存在一些限制,無法指定輸出字段的數據類型(假如需要的話),無法自動裝入相關的數據(復雜屬性),并且因為需要ResultSetMetaData的信息,會對性能有稍微的不利影響。但使用resultMap,這些限制都可以很輕易解決。


三、正題來了,怎么做“通用持久層對象”

1. 表結構:

  每個表都必須包含兩個字段:id和parentId,其他字段按照需求來定義,其他各種索引、約束、關系之類的也按需求定義。

2. 通用的持久層對象,CustomPO:

public class CustomPO {
    protected String moduleTable;  //該PO對應的表名(視圖名)
    protected int id;  //表的id
    protected int parentID;  //父表的id(假如有的話)
    protected Map fieldMap;  //字段Map,核心,用于存儲字段及其值
    public String getModuleTable()
    public void setModuleTable(String moduleTable)
    public int getId()
    public void setId(int id)
    public int getParentID()
    public void setParentID(int parentID)
    public Map getFieldMap()
    public void setFieldMap(Map fieldMap)
    public void copyFieldMap(Map fieldMap)
    //取得字段名列表
    public List getFieldList()
    //設置字段名列表。假如fieldMap沒有相應的字段,則增加,字段值為null;假如有則不增加。
    public void setFieldList(List fieldList)
    //返回字段的“字段名 - 字段值”列表,使用com.fellow.pub.util.KeyValuePair對象作為存儲
    public List getFieldValueList()
}

  那些成員變量的get/set就沒什么說的,主要說說getFieldValueList()這個方法。該方法返回一個列表,列表元素是一個key-value結構,簡單來說就是把字段map序列化。在構造模板sql語句時會體現它的用途。

3. iBatis對象配置文件CustomPO.xml


  
  
            通過id查找
        特點:iterate這個fieldList列表,生成要輸出的字段
    -->
  
  
            插入一條新紀錄
        特點:iterate這個fieldValueList列表,分別取得其元素的key和value值
        注重$號和#號的使用方法,還有最后怎么取得insert后的id值(各種數據庫都可能不同)
    -->
  
    INSERT INTO $moduleTable$ (parentID
      
        $fieldValueList[].key$
      

      )
    VALUES (#parentID#
      
        #fieldValueList[].value#
      

      )
    
      SELECT last_insert_id()
    

  


            更新一條紀錄
        特點:iterate這個fieldValueList列表,分別取得其元素的key和value值
        注重$號和#號的使用方法
    -->
  
    UPDATE $moduleTable$ SET
      
        $fieldValueList[].key$ = #fieldValueList[].value#
      

     WHERE id = #id#
  


    
  
    DELETE FROM $moduleTable$ WHERE id = #id#
  


  要注重的地方如下:

  a. 跟一般的ibatis配置文件不一樣,該配置中沒有包含resultMap,使用的就是resultClass的方式(效率沒那么高的那種)。當然,也可以使用resultMap,這樣就要為每個表寫自己的配置文件了。因此,在該設計沒完成前,我暫時先使用resultClass的方式。

  b. 上面只列舉了最簡單的增刪改以及按id查詢,并沒有更復雜的查詢,為什么呢?因為我還在研究中。。。研究通用的模板sql的寫法。

4. CustomPO對應的DAO:

  我使用了ibaits提供的DAO框架,很好用,不單支持ibatis的框架,還支持Hibernate、JDBC等等,而且是與ibatis本身獨立的,完全可以單獨使用。以后就不用自己寫DAO框架了。一下是該DAO接口:

public interface ICustomDAO {
    /**
     * 通過傳入moduleTable和id取得一條記錄
     */
    CustomPO findByID(String moduleTable, int id) throws Exception;

    /**
     * 通過傳入CustomPO對象取得一條記錄
     * @param po CustomPO 該對象在傳入前應該先設置moduleTable和id參數,
     * 并且使用setFieldList()函數設置字段列表(該設置決定所返回的字段)。
     */
    CustomPO findByID(CustomPO po) throws Exception;

    /**
     * 通過傳入moduleTable和parentID取得一條記錄
     */
    CustomPO findByParentID(String moduleTable, int parentID) throws Exception;

    /**
     * 通過傳入CustomPO對象插入一條記錄
     * @param po CustomPO 該對象在傳入前應該先設置moduleTable和id參數,
     * 并且使用setFieldMap()函數設置“字段-值”對。
     */
    void insert(CustomPO po) throws Exception;

    /**
     * 通過傳入CustomPO對象更新一條記錄
     * @param po CustomPO 該對象在傳入前應該先設置moduleTable和id參數,
     * 并且使用setFieldMap()函數設置“字段-值”對。
     */
    void update(CustomPO po) throws Exception;

    /**
     * 刪除moduleTable和id所對應的記錄
     */
    void delete(String moduleTable, int id) throws Exception;
}

  我沒有把所有的方法都列出來,反正挺簡單的,跟一般的DAO沒什么分別。

  另外列幾個實現的片斷:

  a. 統一的數據裝填函數,需要手工把id和parentID字段去掉。

    protected void fill(Map result, CustomPO po) {
        Long returnId = (Long) result.get("id");
        Long returnParentID = (Long) result.get("parentID");
        result.remove("id");
        result.remove("parentID");
        if (returnId != null) po.setId(returnId.intValue());
        if (returnParentID != null) po.setParentID(returnParentID.intValue());
        po.setFieldMap(result);
    }

  b. 一般的查詢,返回的是一個map,然后再用fill()函數

    //查詢
     Map result = (Map)this.queryForObject("customPO_findByID", po);

    //處理返回結果
    if(result == null)
        po = null;
    else
        fill(result, po);

  c. 增刪改,沒有返回值,值得一提的是增加操作完成后,po里面的id會更新,具體看前面相關的statement。

    //增刪改
    this.insert("customPO_insert", po);
    this.update("customPO_update", po);
    this.delete("customPO_delete", po);


5. 前面是通用的部分,光是通用是不夠的。因此我另外建立了一套配置文件,記錄字段對應關系。看看我所定義的一個配置文件,挺簡單的:


    
    
    
    。。。


  其中,name是字段名,column是字段對應數據表的字段名,type是字段類型,not-null是是否不能為空,unique是是否唯一。只有name這個屬性是必填的,column假如不填默認與name相等,type默認為string,not-null和unique默認為false。

  配置文件的讀取類在這里就省略了。

  為什么要自己定義一套這個框架?似乎挺多此一舉的,但是沒辦法,ibatis配置文件的信息是封閉的,我無法取得。另外我考慮的是:
  a. viewer層:在web開發中,我可以在這套配置框架的基礎上,建立自己的標簽,實現數據自動綁定的功能;GUI開發中也可以做相應的功能。
  b. module層:可以做通用的業務操作,不需要為每個業務都都做獨立的業務邏輯。

四、有什么優點、缺陷

1. 優點:
 a. “通用”,一切都是為了通用,為了減少重復勞動,一個個項目面對不同的業務,其實說到底都是那些操作。各種持久成框架已經帶給我們不少的方便,但是在實際業務邏輯的處理上似乎還沒有一個這樣的框架。
 b. 極大地減少代碼量。前面說了,數據庫改一個字段,PO、DAO、module、JO、viewer、validator全都要改一遍。使用了這套東西,可以把絕大部分的勞動都放在配置文件和UI上。當然,這是完美的設想,對于很多情況,業務邏輯還是要手工寫的。
 c. 似乎沒有c了。

2. 缺點:
 a. 通常通用的東西都缺乏靈活性,在我的實際應用中也發現了這樣那樣的問題,解決方法都是以通用為基本原則。但是假如針對的是某個項目,那就可以針對業務來修改了。
 b. 性能問題。因為使用resultClass,按照文檔所說的,性能沒有resultMap好。當然也可以使用resultMap,如前所說,就要對每個PO寫配置文件了,工作量也不少。
 c. 也似乎沒有c了。

五、后話
  我總是喜歡寫一些通用的東西,總是想把它設計成萬能的。但是經過多次失敗總結出來,我發現通用的東西在很多情況下都等于不能用。但我就是喜歡往通用方面想,這個毛病不知道什么時候才能改得了。其實在Delphi平臺中,我早就實現了相關的東西,但是用delphi總是限制于ADO+Data Module這樣掉牙的模式?,F在轉向java,發現有ibatis、hibernate這么多好的持久層框架,自然有移植必要了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线不卡国产精品| 日韩av综合网站| 欧美黄色片视频| 韩剧1988免费观看全集| 亚洲高清不卡av| 精品久久久久久久久久久久久| 精品激情国产视频| 日本免费在线精品| 国产精品麻豆va在线播放| 欧美专区日韩视频| 国产69精品久久久久9999| 日韩欧美在线国产| 精品视频久久久久久| 亚洲女在线观看| 亚洲日本中文字幕免费在线不卡| 欧美亚洲午夜视频在线观看| 亚洲精品99久久久久中文字幕| 欧美最顶级丰满的aⅴ艳星| 国产精品久久91| 69av在线播放| 亚洲天堂男人天堂| 3344国产精品免费看| 亚洲自拍偷拍区| 久久99青青精品免费观看| 青青a在线精品免费观看| 久久精品色欧美aⅴ一区二区| 日本三级韩国三级久久| 国产在线观看91精品一区| 欧美性xxxxhd| 国产suv精品一区二区| 亚洲网站在线播放| 美女视频黄免费的亚洲男人天堂| 欧美另类精品xxxx孕妇| 欧美性xxxxxx| 亚洲欧洲一区二区三区久久| 久久天天躁狠狠躁夜夜爽蜜月| 欧美在线不卡区| 久久亚洲国产精品成人av秋霞| 亚州精品天堂中文字幕| 国产91精品在线播放| 色偷偷88888欧美精品久久久| 日韩在线不卡视频| 国产福利成人在线| 精品久久久久久亚洲精品| 久久亚洲春色中文字幕| 国产高清视频一区三区| 国产精品都在这里| 日本亚洲欧洲色α| 日韩黄在线观看| 欧美黄色www| 伊人久久五月天| 日韩三级影视基地| 97精品伊人久久久大香线蕉| 日韩精品在线观看一区二区| 中文字幕亚洲综合久久筱田步美| 欧美成人网在线| 欧美性xxxxxxx| 久久亚洲精品小早川怜子66| 欧美成人手机在线| 中文字幕亚洲综合久久筱田步美| 国产精品99导航| 欧美日韩一区二区在线播放| 日韩久久精品电影| 久久影视电视剧免费网站| 91久热免费在线视频| 色综合色综合久久综合频道88| 久久伊人色综合| 91精品久久久久久久久久| 国产不卡视频在线| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲综合在线中文字幕| 欧美激情18p| 亚洲日本欧美日韩高观看| 日韩有码视频在线| 亚洲影院色在线观看免费| 久久久久久久久久久人体| 国产日本欧美一区二区三区| 在线播放日韩专区| 欧美午夜视频一区二区| 欧美国产日韩免费| 国产日韩在线一区| 欧美刺激性大交免费视频| 在线成人一区二区| 成人黄色片在线| 亚洲黄色在线观看| 亚洲视频一区二区三区| 久久99精品视频一区97| 国产日韩精品在线播放| 精品视频中文字幕| 日韩av毛片网| 欧美精品精品精品精品免费| 狠狠色香婷婷久久亚洲精品| 久久久久久久亚洲精品| 91久久国产精品| 久久亚洲国产成人| 久久精品99久久香蕉国产色戒| 欧美精品videossex88| 欧美国产日韩在线| 538国产精品一区二区在线| 草民午夜欧美限制a级福利片| 国产盗摄xxxx视频xxx69| 伊人一区二区三区久久精品| 亚洲福利在线看| 日韩免费精品视频| 色黄久久久久久| 亚洲精品国产拍免费91在线| 在线看片第一页欧美| 精品久久久av| 欧美午夜宅男影院在线观看| 国产精品18久久久久久首页狼| 亚洲欧美国产另类| 成人在线播放av| 91久久国产精品91久久性色| 亚洲精品日韩激情在线电影| 亚洲欧美日韩精品久久| 国语自产精品视频在线看| 精品国产电影一区| 久久久久久有精品国产| 国产九九精品视频| 国产精品99久久久久久白浆小说| 91久久久久久国产精品| 九九热精品视频国产| 亚洲精品网址在线观看| 亚洲资源在线看| 欧美大尺度在线观看| 久久久久久久一区二区| 久久91亚洲精品中文字幕| 亚洲va欧美va国产综合久久| 国内久久久精品| 正在播放国产一区| 九九视频直播综合网| 国产精品99久久久久久久久久久久| 国产精品h在线观看| 国产精品久久久久福利| 日韩**中文字幕毛片| 国产啪精品视频| 福利一区福利二区微拍刺激| 爱福利视频一区| 欧美日韩国产综合新一区| 性色av一区二区三区在线观看| 欧美刺激性大交免费视频| 欧美电影免费观看电视剧大全| 91美女片黄在线观| 午夜精品久久久久久久久久久久| 国产精品美女主播| 国产精品手机播放| 国产激情久久久| 久久精品国产欧美亚洲人人爽| 黑人精品xxx一区一二区| 黄色成人av网| 国产成人精彩在线视频九色| www高清在线视频日韩欧美| xvideos亚洲| 国产亚洲精品一区二区| 久久艹在线视频| 欧美国产一区二区三区| 欧美大胆a视频| 91视频88av| 美女福利精品视频| 亚洲第一福利在线观看| 久久69精品久久久久久国产越南| 亚洲自拍偷拍色图| 亚洲自拍中文字幕| 日韩在线精品一区|