<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    自己實現ORM

    這篇文章源自剛開發的一個小項目。項目中并未使用hibernate,但我還是要把它放在hibernate欄下。理由很簡單,技術是死的,而人是活的,能熟練的使用一項技術不算什么,但能恰當的選擇相應的技術,甚至自己想出辦法來優雅的解決實際問題,就需要一定的積累了。而這種積累就來源自項目實踐和對各種技術其實質的理解。我記得在某個論壇上某人(名字忘了)說過一句話:如果學習hibernate只是學會了怎么mapping,怎么寫DAO,就只是學了皮毛,學hibernate就要從中了解到很多持久層的最佳實踐。我深以為然!

    項目很簡單,頁面也不多,但頁面字段較多(100多個),相互間還有一定關聯。而且存入數據庫類型多樣,有varchar, integerdate幾種。我是很希望用hibernate來實現的,但考慮到項目時間較緊,而我對hibernate的了解還是停留在理論和學習階段(有點落后啊!),采用不熟悉的技術項目風險較大,所以還是使用普通JDBC作為持久層方案。面對這么多字段,一個個去拼SQL語句,代碼臃腫,而且容易出錯,也難以維護。我得對這幾種類型的字段,在插入、更新和讀取時分別處理,寫一個private方法,傳入類型和字段名,讀取相應的ResultSet,是不錯的方法,至少是比較優雅的實現。

    什么是優雅?動態設置,避免hardcode,就是優雅;層次清晰,層次間耦合最低,就是優雅;只寫一處,處處引用,就是優雅;代碼精煉,避免過度設計,就是優雅;接口明確,調用簡單,就是優雅;調試容易,便于測試,就是優雅。。。。。。而優雅的設計和實現,在可擴展性、可維護性、開發效率、開發成本等方面都是最好的。

    Hibernate就是優雅的設計,它通過配置文件,建立實體與數據庫的映射,動態的生成SQL語句,避免了對屬性字段的hardcode,這就是它最本質的思想。我不使用hibernate,但一樣可以借鑒它的思想,我不需要對象容器、分頁查詢等等高級功能,因此可以簡單的實現類似ORM的功能。

    首先,定義一個配置類,將數據庫字段和類型定義下來。按照常規的做法,從頁面字段到對象屬性到數據庫都應該建立映射,這樣需要生成相應的映射類。為簡單起見,我不使用POJO,而是使用Map作為數據的載體,key就是數據庫字段名,在頁面端我也用數據庫字段名作為域的名稱。這樣我直接通過名稱建立映射,犧牲了擴展性和靈活性,但簡化了操作,也無需映射類,只要一個映射Mapkey是數據庫字段名,value是我自己定義的字段類型。以后動態生成SQLMap傳輸對象,以及從頁面request動態生成Map都是基于這個配置。

    接下來,就很簡單了。先處理DAO的動態生成SQL代碼,下面是生成insertSQL的方法,

    private static String generateInsertScoreSQL(Map m, String studentId) {

                  StringBuffer sb 
    = new StringBuffer();

                  StringBuffer sb2 
    = new StringBuffer();

     

                  sb.append(
    "insert into STUDENT_SCORE (id,");

                  sb2.append(
    " values('");

                  sb2.append(studentId);

                  sb2.append(
    "',");

                  
    for (Iterator iter = m.keySet().iterator(); iter.hasNext();) {

                         String name 
    = (String) iter.next();

                         String value 
    = (String) m.get(name);

                         sb.append(name);

                         sb.append(
    ",");

     

                         String type 
    = (String) ScoreColumnMapping.scoreItemMap().get(name);

                         
    if (ScoreColumnMapping.INT.equalsIgnoreCase(type)) {

                                
    if (value == null || value.length() == 0{

                                       sb2.append(
    "null,");

                                }
     else {

                                       sb2.append(Integer.parseInt(value));

                                       sb2.append(
    ",");

                                }


                         }
     else if (ScoreColumnMapping.STRING.equalsIgnoreCase(type)) {

                                sb2.append(
    "'");

                                sb2.append(value);

                                sb2.append(
    "',");

                         }


                  }


                  sb.replace(sb.length() 
    - 1, sb.length(), ")");

                  sb2.replace(sb2.length() 
    - 1, sb2.length(), ")");

                  log.info(sb.toString() 
    + sb2.toString());

                  
    return sb.toString() + sb2.toString();

           }

    生成updateSQL的代碼:

         

      private static String generateUpdateScoreSQL(Map m, String studentId) {

                  StringBuffer sb 
    = new StringBuffer();

     

                  sb.append(
    "update STUDENT_SCORE set ");

     

                  
    for (Iterator iter = m.keySet().iterator(); iter.hasNext();) {

                         String name 
    = (String) iter.next();

                         String value 
    = (String) m.get(name);

                         sb.append(name);

                         sb.append(
    "=");

     

                         String type 
    = (String) ScoreColumnMapping.scoreItemMap().get(name);

                         
    if (ScoreColumnMapping.INT.equalsIgnoreCase(type)) {

                                
    if (value == null || value.length() == 0{

                                       sb.append(
    "null,");

                                }
     else {

                                       sb.append(Integer.parseInt(value));

                                       sb.append(
    ",");

                                }


                         }
     else if (ScoreColumnMapping.STRING.equalsIgnoreCase(type)) {

                                sb.append(
    "'");

                                sb.append(value);

                                sb.append(
    "',");

                         }


                  }


                  sb.replace(sb.length() 
    - 1, sb.length(), "");

     

                  sb.append(
    " where id='");

                  sb.append(studentId);

                  sb.append(
    "'");

     

                  log.info(sb.toString());

                  
    return sb.toString();

           }

    ResultSet中生成Map對象的代碼:

    private static void getScoreFromRs(ResultSet rs, Map m) throws SQLException {

                  String name;

                  String type;

                  
    for (Iterator iter = ScoreColumnMapping.scoreItemMap().keySet()

                                .iterator(); iter.hasNext();) 
    {

                         name 
    = (String) iter.next();

                         type 
    = (String) ScoreColumnMapping.scoreItemMap().get(name);

                         
    if (ScoreColumnMapping.INT.equalsIgnoreCase(type)) {

                                Object value 
    = rs.getObject(name);

                                m.put(name, String.valueOf(value 
    == null ? "" : value));

                         }
     else if (ScoreColumnMapping.STRING.equalsIgnoreCase(type)) {

                                String value 
    = rs.getString(name);

                                m.put(name, value);

                         }


                  }


     

           }

    因為只有一個DAO采用這種方式,所以我用private方法,這可以通過重構,將其抽取到Util類中,供所有DAO使用。頁面端也很簡單,我做個Fa?ade類,它獲取request,并將其處理成一個Map,然后交給數據層處理(因為比較簡單,省去了業務層),代碼如下:

    Map m = new HashMap();

            
    for (Iterator iter = ScoreColumnMapping.scoreItemMap().keySet()

                    .iterator(); iter.hasNext();) 
    {

                String name 
    = (String) iter.next();

                String value 
    = request.getParameter(name);

                         ……

    m.put(name, value);

    ……

     

    所有方法中未出現一個字段名稱,全部是從配置類中動態生成。這樣帶來了很多好處:

    u       擴展容易,如果需增加字段,無需更改核心代碼,只要修改配置文件和數據庫表定義,然后頁面上加加域

    u       開發效率提高,整個核心代碼,幾個小時搞定,然后就是處理表單域間的關系和顯示邏輯,DAO層快速開發,而且基本減少出錯的可能性(出錯也是配置文件錯)。

    u       排錯容易,我定義了清晰的Exception機制和log機制,出錯只記錄一次,并通過log.info記錄生成的SQL語句,很容易根據這些信息查出錯誤原因并解決。

     

    呵呵,其實很多東西并不如我們想象的那么復雜,看東西要看其本質。普元不是提出什么面向構件,xml數據總線的理論嗎?它直接傳xml文件?還不是用Map做載體,然后動態生成SQL語句。我這個東西擴展出去,定義完善的xml配置,然后多幾層封裝,然后加上些企業特性,也能出去吹吹的。

    但這也是權宜之計,以后我還是會使用hibernate,而不是把這個東西做完善。不重新發明輪子,這也是open source社區的共識。但自己做做也挺有意義的,起碼能培養自己的創造力,也能對技術實質有第一手的了解,而且很開心。

    做點東西,學點技術,然后進行些反思和總結,這是我一貫的做法。也希望能對大家有所啟發。

    posted on 2005-10-25 13:55 pesome 閱讀(2579) 評論(2)  編輯  收藏 所屬分類: Spring+Struts+Hibernate

    評論

    # re: 自己實現ORM 2005-10-26 23:41 BlueO2

    JSTL有直接resultset轉化為result的類 而result可轉化為sortedMap 你又可以省個輪子啦 Hoho 而且比你的還rounder
    不過這個似乎不是ORM ORM為了以oo的方式來操作數據庫,目前僅僅是簡單但是很長的sql得封裝而已。就是個應用DAO模式的持久層,離ORM還差好遠  回復  更多評論   

    # re: 自己實現ORM 2005-10-27 09:36 zhangjun

    呵呵,的確不算ORM,頂多是MRM(Map Relation Mapping)。但對于小項目,特別是沒有什么業務邏輯的項目,還是挺方便的。也不需要什么對象,直接用map就搞定,put,get用的也簡單,還省得用什么reflaction或CGILIB。適合就是最好的,至少我這個項目用的很爽。也謝謝指教,大家討論嘛!  回復  更多評論   

    <2005年10月>
    2526272829301
    2345678
    9101112131415
    16171819202122
    23242526272829
    303112345

    導航

    統計

    公告

    主要記錄作者在學習java中的每一步足跡。除非特別說明,所有文章均為本blog作者原創,如需轉載請注明出處和原作者,如用于商業目的,需跟作者本人聯系。
    歡迎大家訪問:

    常用鏈接

    留言簿(16)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    相冊

    收藏夾

    java技術

    人間百態

    朋友們的blog

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 久久久久亚洲国产| 日韩在线免费电影| ssswww日本免费网站片| 亚洲五月综合网色九月色| 亚洲gv白嫩小受在线观看| 亚洲精品人成无码中文毛片 | 亚洲高清无码在线观看| 亚洲精品动漫免费二区| 欧洲精品99毛片免费高清观看 | 国产精品亚洲成在人线| 国产精品国产免费无码专区不卡| 成人免费视频69| 老汉精品免费AV在线播放| 免费一区二区无码东京热| 色屁屁在线观看视频免费| 亚洲日韩精品无码专区| 亚洲色欲色欲www| 亚洲人成黄网在线观看| 久久精品国产亚洲av麻豆小说 | 少妇亚洲免费精品| 美女黄色免费网站| 国产精品亚洲а∨无码播放不卡 | 国产免费午夜a无码v视频| 毛色毛片免费观看| 久久精品女人天堂AV免费观看| 国产一卡2卡3卡4卡无卡免费视频| 97在线视频免费| 最新黄色免费网站| 亚洲免费观看网站| 波多野结衣在线免费视频| 久久笫一福利免费导航| 国产一卡二卡3卡四卡免费| 最新猫咪www免费人成| 免费看少妇作爱视频| 成人永久免费高清| 波多野结衣一区二区免费视频| 免费在线观看亚洲| 亚洲女人被黑人巨大进入| 综合亚洲伊人午夜网| 久久精品亚洲综合一品| 97se亚洲综合在线|