乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      ibatis支持枚舉類型

       KILLKISS 2010-07-06
      很多應(yīng)用中,數(shù)據(jù)庫表結(jié)構(gòu)都會存在一些狀態(tài)字段。在關(guān)系性數(shù)據(jù)庫中,一般會用VARCHAR類型。使用ibatis的應(yīng)用,傳統(tǒng)做法,往往會使用String的屬性,與之對應(yīng)。
      例如一張member表,結(jié)構(gòu)設(shè)計如下:

      其中status為狀態(tài)字段。

      ibatis中,使用class MemberPO 與之mapping,設(shè)計往往如下:
      public class MemberPO implements Serializable {
          
      private Integer id;
          
      private String loginId;
          
      private String password;
          
      private String name;
          
      private String profile;
          
      private Date gmtCreated;
          
      private Date gmtModified;
          
      private String status;

         
      //getter/setters

      缺點:
      1)不直觀,沒人會知道status具體有哪些值。在缺乏文檔,并且歷史悠久的系統(tǒng)中,只能使用“select distinct(status) from member”,才能得到想要的數(shù)據(jù)。如果是在千萬級數(shù)據(jù)中,代價太大了;
      2)類型不安全,如果有人不小心拼寫錯誤,將會導致錯誤狀態(tài)。假設(shè)上面列子中,status只允許ENABLED/DISABLED,如果一不小心,memberPO.setStatus("ENABLEDD"),那么將會造成臟數(shù)據(jù)。

      既然jdk5之后,引入了enum,是否可以讓ibatis支持enum類型呢?事實上,最新的ibatis版本,已經(jīng)支持enum類型(本文使用的是2.3.4.726版本--mvn repsitory上最新的版本)。
      以上代碼可以修改成:
      1)Status類:
      public enum Status {

          
      /** enabled */
          ENABLED,

          
      /** disabled */
          DISABLED;

      2)MemberPO類:
      public class MemberPO implements Serializable {
          
      private Integer id;
          
      private String loginId;
          
      private String password;
          
      private String name;
          
      private String profile;
          
      private Date gmtCreated;
          
      private Date gmtModified;
          
      private Status status;

          
      //getter/setters

      除此之外,其他均無需改動。
      為什么呢?ibatis如何知道VARCHAR/Enum的mapping呢?
      看過ibatis源碼的同學,知道,ibatis是通過jdbcType/javaType得到對應(yīng)的TypeHandler做mapping處理的。ibatis有基本類型的TypeHandler,比如StringTypeHandler,IntegerTypeHandler等等。在最新版本中,為了支持enum,增加了一個EnumTypeHandler。

      并且在TypeHandlerFactory中,加了對enum類型的判斷,請看:
      public TypeHandler getTypeHandler(Class type, String jdbcType) {
          Map jdbcHandlerMap 
      = (Map) typeHandlerMap.get(type);
          TypeHandler handler 
      = null;
          
      if (jdbcHandlerMap != null) {
            handler 
      = (TypeHandler) jdbcHandlerMap.get(jdbcType);
            
      if (handler == null) {
              handler 
      = (TypeHandler) jdbcHandlerMap.get(null);
            }
          }
          
      if (handler == null && type != null && Enum.class.isAssignableFrom(type)) {
            handler 
      = new EnumTypeHandler(type);
          }
          
      return handler;
        }
      ibatis使用了取巧的方法,當取不到基本類型的handler時候,判斷javaType是否是Enum類型--Enum.class.isAssignableFrom(type),如果是,則使用 EnumTypeHandler進行mapping處理。

      為什么說它取巧,原因是早期ibatis設(shè)計過程中,自定義的接口無法得到具體的java class type。故早期的ibatis中,要實現(xiàn)對enmu的支持,非常苦難。而新版本中,為了達到這個功能,作者直接修改了TypeHandlerFactory的實現(xiàn),打了一個補丁,如下:
      if (handler == null && type != null && Enum.class.isAssignableFrom(type)) {
            handler 
      = new EnumTypeHandler(type);
      }
      這個設(shè)計有悖于和早前的設(shè)計思想。早期,TypeHandler都是通過public void register(Class type, String jdbcType, TypeHandler handler)方式事先注冊到factory中的,而這次,是在運行期,通過new方法動態(tài)得到EnumTypeHandler。
      當然,新版本ibatis能支持enum,已經(jīng)是一件開心的事情了。

      Status枚舉類除了描述狀態(tài),就足夠了嗎?回想起很多應(yīng)用,我是做web開發(fā)的,在view層(velocity,jsp,等),見多了類似這樣的代碼:
      #if($member.getStatus()==Status.ENABLED)開通#elseif($member.getStatus()==Status.DISABLED)關(guān)閉#end

      <select>
        
      <option value="ENABLED" #if($member.getStatus()==Status.ENABLED) selected="selected"#end >開通</option>
        
      <option value="DISABLED" #if($member.getStatus()==Status.DISABLED) selected="selected"#end >關(guān)閉</option>
      </select>

      web層需要多少個頁面,就需要維護多少份這樣的代碼;以后每添加/刪除一種狀態(tài),多個地方都需要修改,還要擔心邏輯不一致。

      而事實上,關(guān)于狀態(tài)的信息描述,按照職責分,就應(yīng)該由枚舉類來維護:
      1)制定一個接口,EnumDescription.java
      public interface EnumDescription {

          
      public String getDescription();

      }
      2)寫一個ResourceBundleUtil.java,通過Properties文件得到描述信息:
      public class ResourceBundleUtil {

          
      private ResourceBundle resourceBundle;

          
      public ResourceBundleUtil(String resource) {
          
      this.resourceBundle = ResourceBundle.getBundle(resource);
          }

          
      public ResourceBundleUtil(String resource, Locale locale) {
          
      this.resourceBundle = ResourceBundle.getBundle(resource, locale);
          }

          
      public String getProperty(String key) {
          
      return resourceBundle.getString(key);
          }

      }
      3)Status等枚舉類實現(xiàn)EnumDescription:
      public enum Status implements EnumDescription {

          
      /** enabled */
          ENABLED,

          
      /** disabled */
          DISABLED;

          
      private static ResourceBundleUtil util = new ResourceBundleUtil(Status.class.getName());

          
      public String getDescription() {
             
      return util.getProperty(this.toString());
          }

      }

      這樣,有什么好處:
      1)通過Properties文件,支持國際化。
      2)描述信息統(tǒng)一由自己來維護,方便維護,并且顯示層邏輯簡化,如:
      $member.getStatus().getDescription()

      <select>
        #foreach($status in $Status.values())
          
      <option value="$status" #if($member.getStatus()==$status)selected="selected"#end >$status.getDescription()</option>
        #end
      </select>

      ##############################################################################
      那么使用老版本ibatis的客戶怎么辦呢?就像我們公司使用ibatis 2.3.0,難道只能眼饞著?解決方案:
      1)升級到最新版本。 :)
      2)ibatis提供了TypeHandler/TypeHandlerCallback接口,針對每種枚舉類型,寫相應(yīng)的TypeHandler/TypeHandlerCallback的接口實現(xiàn)即可--工作量大,重復的勞動力。
      主要是早期ibatis TypeHandler無法得到j(luò)avaType類型,無法從jdbc value轉(zhuǎn)成對應(yīng)的枚舉。在我看來,TypeHandler是作mapping用的,它至少有權(quán)知道javaType。
      3)實現(xiàn)偽枚舉類型(允許繼承)來實現(xiàn)狀態(tài)類型安全,而拋棄jdk5的方式--不方便日后升級。


      不知道大家是否還有更好的方案?

      本文涉及演示代碼如下:
      演示代碼
      workspace file encoding:utf-8
      build tool: maven
      repository:spring/2.5.5;ibatis/2.3.4.726

       

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多