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

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



          逐個逐個地打開這些java文件和xml文件來看,我發(fā)現(xiàn)了幾個特點:

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

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

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

          ★Channel

          經(jīng)過和impl.basic包中Channel的比較,發(fā)現(xiàn)兩者的實現(xiàn)有如下的不同:

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

          我們來比較這兩個包中構(gòu)造方法的代碼:

          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();
              }

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

          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實現(xiàn)包中,由于使用了HashSet,只能使用逐個迭代的方式來輪詢檢查,當(dāng)item的數(shù)目比較多時,無疑效率被第一種低了很多。在作者的注釋中也提到了可以使用map。特別的這個getItem并非從數(shù)據(jù)庫的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"屬性,這意味著當(dāng)我們從數(shù)據(jù)庫中檢索Channel時,對應(yīng)的item都會被檢出,然后填充到entity bean中,所以此時直接從Channel中的HashSet中拿就可以了。

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

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


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

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


          網(wǎng)站導(dǎo)航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          <2009年12月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(21)

          隨筆分類

          隨筆檔案

          BlogJava熱點博客

          好友博客

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 六枝特区| 临夏市| 原平市| 扎兰屯市| 陕西省| 徐水县| 茌平县| 科技| 威信县| 湟源县| 渭南市| 巴塘县| 青龙| 梧州市| 祥云县| 浪卡子县| 化州市| 常德市| 洪江市| 平定县| 张家界市| 巢湖市| 陆良县| 黄浦区| 安顺市| 肥乡县| 石门县| 卓尼县| 交口县| 辉县市| 盈江县| 探索| 任丘市| 杭锦后旗| 吉安市| 诸城市| 红原县| 唐山市| 顺平县| 秀山| 治多县|