|
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 |
|