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 阅读(150) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航:
 
<2009年12月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

常用链接

留言簿(19)

随笔分类

随笔档案

BlogJava热点博客

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜