posts - 262,  comments - 221,  trackbacks - 0
          Informa的core包定義了一系列的核心接口,basic使用基于內存的模式實現了這些接口。但是這些基于內存的實現在應用程序退出或者機器斷電,重啟后將不復存在,所以Informa又提供了另外一個基于Hibernate實現的包:impl.hibernate。

          和一般的Hibernate Entity domain一樣,在Informa的impl.hibernate包下,包含了兩種類型的文件:java文件和Hibernate的XML映射文件。



          逐個逐個地打開這些java文件和xml文件來看,我發現了幾個特點:

           A.多數的Hibernate實現和Basic實現的代碼都是一摸一樣的,這一點并不奇怪。因為本來就是實體bean
           B.所有的Hibernate實現都沒有在構造函數中調用IdGenerator生成ID,使用了數據庫生成的Id

          在前面一節《RSS工具開發手記(08)---Informa的build.xml》中,我們提到了Informa的自定義task:schemaexport。這個task依靠于Hibernate的內在類“org.hibernate.tool.hbm2ddl.SchemaExportTask”在CLASSPATH下搜尋hbm文件,然后把這些映射文件導出為ddl文件。

          在這個包里面比較值得研究的有下面幾個:
           A.Channel
           B.ChannelBuilder
           C.ChannelUpdatePeriodUserType
           D.SessionHandler

          ★Channel

          經過和impl.basic包中Channel的比較,發現兩者的實現有如下的不同:

           A.構造方法中多了3個方法,兩個是使用title和location來構造的,一個是使用Element,title,location來構造的
           B.從Hibernate中檢索出來的是不用設置ID的,而從內存中生成的必須使用IdGenerator產生唯一ID
           C.basic實現中沒有getLocationString方法和setLocationString方法
           D.basic實現中沒有getSiteString方法和setSiteString方法
           E.basic實現中沒有getGroup方法和setGroup方法
           F.basic實現中沒有getFormatString和setFormatString方法
           G.basic中沒有setItems方法,而且getItems方法中的實現不同(basic采用了同步的hashset,而hibernate沒有)
           H.basic中的addItem方法是添加到hashmap,而hibernate中的addItem方法是添加到hashset
           I.basic中的getItem方法是直接從map中根據ID獲取,而hibernate中的getItem是采用Iterator方法輪詢,而且不是從數據庫中獲取

          我們來比較這兩個包中構造方法的代碼:

          impl.basic包
            public Channel(Element channelElement, String title) {
               
          this.id = IdGenerator.getInstance().getId();
               
          this.channelElement = channelElement;
               
          this.title = title;
               
          this.items = Collections.synchronizedMap((new LinkedHashMap<Long, ItemIF>()));
               
          this.categories = new ArrayList<CategoryIF>();
               
          this.observers = new ArrayList<ChannelObserverIF>();
               
          this.format = ChannelFormat.UNKNOWN_CHANNEL_FORMAT;
               
          this.lastUpdated = new Date();
            }

          impl.hibernate包
              public Channel(Element channelElement, String title, String location) {
                  
          this.channelElement = channelElement;
                  
          this.title = title;
                  setLocationString(location);
                  
          this.items = new HashSet<ItemIF>();
                  
          this.categories = new ArrayList<CategoryIF>();
                  
          this.observers = new ArrayList<ChannelObserverIF>();
                  
          this.groups = new HashSet<ChannelGroup>();
                  
          this.format = ChannelFormat.UNKNOWN_CHANNEL_FORMAT;
                  
          this.lastUpdated = new Date();
              }

          首先最明顯的一個區別就是Id的生成不同了,其次在impl.basic中使用同步的HashMap來存儲items,而在impl.hibernate中使用了HashSet。但是在下面impl.hibernate的getItem的方法中,兩者的效率明顯有了區別:

          impl.basic
           public ItemIF getItem(long anId) {
              
          return (ItemIF) items.get(new Long(anId));
            }

          impl.hibernate
              public ItemIF getItem(long itemId) {
                  
          // TODO: improve performance
                  
          // hibernate query cannot be used (not possible: no session object)
                  
          // may be use transient map: items.get(new Long(id));
                  ItemIF theItem = null;
                  Iterator it 
          = items.iterator();
                  
          while (it.hasNext()) {
                      ItemIF curItem 
          = (ItemIF) it.next();
                      
          if (curItem.getId() == itemId) {
                          theItem 
          = curItem;
                          
          break;
                      }

                  }

                  
          return theItem;
              }


          在Hibernate實現包中,由于使用了HashSet,只能使用逐個迭代的方式來輪詢檢查,當item的數目比較多時,無疑效率被第一種低了很多。在作者的注釋中也提到了可以使用map。特別的這個getItem并非從數據庫的ITEMS表取出的。為什么要這樣做呢?

          在查看了Channel的xml映射文件后,我有了一點頭緒
                  <set name="items" table="ITEMS" lazy="false" inverse="true"
                      cascade
          ="all-delete-orphan">
                      
          <key column="CHANNEL_ID" />
                      
          <one-to-many class="de.nava.informa.impl.hibernate.Item" />
                  
          </set>

          注意其中的lazy="false"屬性,這意味著當我們從數據庫中檢索Channel時,對應的item都會被檢出,然后填充到entity bean中,所以此時直接從Channel中的HashSet中拿就可以了。

          至于同步方面我想原因可能是:impl.basic包中的實現是在內存中實現的,所以對于items必須進行同步。因此使用了Collections.synchronizedMap對訪問或存儲的item進行同步。而hibernate實現包中由于是Hibernate管理同步,所以不需要顯式地使用Collections.synchronizedSet來同步這個Set。

          至于為什么在basic和hibernate包中有些屬性和方法是不存在的,構造方法也有不同,這兩點還有待于和作者探討。


          -------------------------------------------------------------
          生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
          posted on 2009-12-28 10:51 Paul Lin 閱讀(237) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2009年12月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(21)

          隨筆分類

          隨筆檔案

          BlogJava熱點博客

          好友博客

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 雅安市| 陆良县| 南宁市| 叶城县| 乐都县| 义马市| 沁源县| 沾化县| 宜良县| 元氏县| 黑河市| 麻栗坡县| 河北区| 邢台县| 乐平市| 休宁县| 宜都市| 铜山县| 花垣县| 连云港市| 安溪县| 旅游| 丰顺县| 团风县| 涞源县| 葵青区| 绥德县| 东山县| 宜川县| 湖南省| 定襄县| 贡嘎县| 丰镇市| 景洪市| 新乐市| 东乡县| 儋州市| 东城区| 邢台县| 德清县| 义乌市|