12
返回列表 发新帖
楼主: Sky-Tiger

Remote Lazy Loading in Hibernate

[复制链接]
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
11#
 楼主| 发表于 2009-5-18 21:57 | 只看该作者
roxyInterceptor's Implementation

Finally, the actual implementation to load an entity and fetch the data in the remote bean is shown here.

Class cls = Class.forName(
                className,
                false,
                Thread.currentThread().getContextClassLoader())
Session currSession = ...//Hibernate Session
Object obj = currSession.get(cls, id); //Get persistent data from db
...
return ((HibernateProxy) obj).getHibernateLazyInitializer()
                                        .getImplementation();

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
12#
 楼主| 发表于 2009-5-18 21:57 | 只看该作者
azyInitializeEntity implementation in LazyInitializerBean.
Testing

We have finally built a simple component to lazy load our data from a remote layer. To test it, we need to make Hibernate, use our Tuplizer component. This can be done by adding a tuplizer tag in hibernate mapping file for our entity.

<hibernate-mapping ...>
  <class name=...>
   <tuplizer entity-mode="pojo" class="package.CustomTuplizer"/>
...

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
13#
 楼主| 发表于 2009-5-18 21:57 | 只看该作者
Adding Tuplizer Component to Hibernate Mapping File.

Now deploy the application, and run it. You can create a test client, that invokes a remote bean to load data from Hibernate Session, as shown below.

TestHome home = ... //remote look-up TeastBean
TestRemote remote = home.create();
TestObj obj = remote.getLazyEntity(); //calls session.load(Object) on remote bean
//obj is a lazy initialized object whose calls will be intercepted by above ProxyInterceptor
...

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
14#
 楼主| 发表于 2009-5-18 21:57 | 只看该作者
Adding Tuplizer Component to Hibernate Mapping File.
Lazy Loading Collections

Unlike Entities, lazy loading collections are pretty straight-forward ,also Hibernate provides direct support for initializing collections of any type. Let's look at Hibernate's collection initialization mechanism first.

Every time Hibernate encounters a collection during initialization, it creates a CollectionType object to map the actual collection values. Examples of such CollectionType supported by Hibernate are BagType, SetType, ListType, MapType, ArrayType and these types are self explanatory.

These collection type objects hold a value object containing the actual collection values and hence acts as a wrapper for the actual collection. The reason for creating wrappers is that these wrappers help to track the state of the collection and even provide lazy initialization support.

Hibernate provides in-built wrappers for some collections, they are listed below,

PersistentBag - representing an Unordered List,
PersistentSet - representing a Set,
PersistentList - representing an Ordered List,
PersistentMap - representing a Map,
PersistentArrayHolder- representing an Array, etc.

In order to create a lazy loadable collection, we need to create a collection type object and define it via Collection-Type attribute in Hibernate Mapping file. We'll use Set to represent our collection and add a lazy loading capability for it.

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
15#
 楼主| 发表于 2009-5-18 21:58 | 只看该作者
CustomCollectionType and UserCollectionType

When Hibernate finds a collection-type attribute in Hibernate Mapping file, it creates a CustomCollectionType object, which maps the collection representation with a user written collection type.

The value for collection-type attribute is our own implementation of collection type and that must implement UserCollectionType interface. This collection type object instance is created and added to CustomCollectionType object created earlier.
Approach

The flow diagram shows our approach for lazy loading the collection from a remote client.

Flow diagram for loading the collection from client

In order to achieve this implementation, we need to create a collection type called LazyCollectionType, a wrapper for our collection called LazyPersistentSet, a replacement object for this wrapper called LazyCollectionRef (this will be shared with the client) and finally a Collection reference at the client side called LazyCollection.

This LazyCollection when accessed will invoke the remote Bean to initialize and load the underlying collection (from persistent storage) and returns the set. This LazyCollection once initialized will be cached at the client side for future access.

Now let us walkthrough through the details of the mentioned components.

First we need to tell Hibernate to use our Collection Type implementation.

<set name=... collection-type="package.LazyCollectionType">
<key column=.../>
...
<one-to-many class=.../>

106551935.jpg (39.77 KB, 下载次数: 6)

106551935.jpg

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
16#
 楼主| 发表于 2009-5-18 21:58 | 只看该作者
Add collection-type attribute to Hibernate Mapping File.

Now that Hibernate creates a LazyCollectionType and adds it to CustomCollectionType component (as talked above). Once this collection type is added, Hibernate invokes the instantiate method on this collection type, to get the wrapper for the underlying collection.

As we are using Set as the collection, we need to return a Set wrapper called LazyPersistentSet of type PersistenSet.

@implemented
public PersistentCollection instantiate(SessionImplementor session,
    CollectionPersister persister) throws HibernateException {
        return new LazyPersistentSet(session);
}
@implemented
public PersistentCollection wrap(SessionImplementor session,
            Object collection) {
        return new LazyPersistentSet(session, (Set) collection);
}
@implemented
public Class getReturnedClass() {
return Set.class;
}
@implemented
public Object instantiate(int anticipatedSize) {
// HashSet to hold collection values
return anticipatedSize <= 0
                       ? new HashSet()
                       : new HashSet(anticipatedSize);
}

LazyCollectionType implementation.

The last instantiate method creates an empty Set for holding the collection values, in this case its going to be an HashSet to hold our collection values.

The next step is to override the Serialization process for LazyPersistentSet wrapper.Upon Serialization, the wrapper objects returns a replacement object called LazyCollectionRef, which will be shared with the remote client. LazyCollectionRef contains the identity of the actual collection (like collection id, role etc).

Object writeReplace() throws ObjectStreamException {
        //get from cache, if already initialized
        ...
        //if not...
        LazyCollectionRef ref = new LazyCollectionRef();
        ref.setId(super.getKey());
...
        return ref;
}

Overriding the Serialization of LazyPersistentSet.

When LazyCollectionRef reaches the remote client, it will be de-serialized to return an AbstractSet implementation called LazyCollection.

Since LazyCollection is an AbstractSet implementation , we'll implement abstract methods that will look-up the remote bean and initializes the underlying collection. For example, an implementation of LazyCollections's iterator method is shown below.

//iterator method implemented
public Iterator iterator() {
if (this.collection == null) {
//look-up remote bean and load collection
                    this.collection = (Set)
LazyInitializerRemote.lazyInitializeCollection(
reference.getRole(),reference.getId());
}//add exception handling
    return this.collection.iterator();
}

Load collection via Remote bean

This collection once initialized can be stored internally and can be retrieved from cache without needing to load it again.

Finally, the actual implementation to load collections in the remote bean is shown here.

PersistenceContext context =
                ((SessionImplementor)currSession).getPersistenceContext();
CollectionPersister persister =
                ((SessionFactoryImplementor) sessFactory)                                                               
                                .getCollectionPersister(role);
CollectionKey key = new CollectionKey(persister, id, EntityMode.POJO);
PersistentCollection collection = context.getCollection(key);
// collection - contains set containing actual data

lazyInitializeCollection implementation in LazyInitializerBean

使用道具 举报

回复
论坛徽章:
350
2006年度最佳版主
日期:2007-01-24 12:56:49NBA大富翁
日期:2008-04-21 22:57:29地主之星
日期:2008-11-17 19:37:352008年度最佳版主
日期:2009-03-26 09:33:53股神
日期:2009-04-01 10:05:56NBA季后赛大富翁
日期:2009-06-16 11:48:01NBA季后赛大富翁
日期:2009-06-16 11:48:01ITPUB年度最佳版主
日期:2011-04-08 18:37:09ITPUB年度最佳版主
日期:2011-12-28 15:24:18ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05
17#
 楼主| 发表于 2009-5-18 21:58 | 只看该作者
Conclusion

So far we have seen a way to load entities and collection from remote client. When I say remote client, it just need not be thin/fat client that runs on a remote machine, even components in other layers can act as a client. Bottom line is that, this approach helps to initialize data from anywhere out of the Hibernate Session.

Next thing to bring to the table is, how good the performance of remote lazy loading. Typically for entities the memory foot print can be considered low and applying remote lazy loading will reduces the performance in terms of number client/server calls, more proxy objects in heap etc. But just the memory foot print should not be the deciding factor for lazy loading entities.

Remote lazy loading can yield a better performance for collections. Even other fetching strategies of Hibernate can be applied to increase the performance of remote lazy loading, like using pagination, lazy fetching object hierarchies, etc.

使用道具 举报

回复
论坛徽章:
131
乌索普
日期:2017-09-26 13:06:30马上加薪
日期:2014-11-22 01:34:242014年世界杯参赛球队: 尼日利亚
日期:2014-06-17 15:23:23马上有对象
日期:2014-05-11 19:35:172014年新春福章
日期:2014-04-04 16:16:58马上有对象
日期:2014-03-08 16:50:54马上加薪
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
18#
发表于 2009-5-18 22:53 | 只看该作者
不懂java

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表