Good <time-of-day>!

I'm writing a custom "lazy materialized" multimap collection for Hibernate. The main reason I'm doing this is that I want to use 2nd-level cache.

So far, I've found several problems with the way caching is implemented in Hibernate:

1. Collections are not cached unless they are completely initialized. That kind of kills the possibility of cached extra lazy collections.

2. Collection loading can be VERY slow. The "initializeFromCache" method of the built-in Hibernate collections looks something like:
========
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
        throws HibernateException {
                Serializable[] array = ( Serializable[] ) disassembled;
                int size = array.length;
                beforeInitialize( persister, size );
                for ( int i = 0; i < size; i++ ) {
list.add( persister.getElementType().assemble( array[i], getSession(), owner ) );
                }
        }
========
If the collection elements are pushed out of the cache (and its a quite probable situation with large collections) - we'll have N+1 selects problem.

3. Mass operations API for caches is not used in Hibernate. Some caches support bulk loading APIs (usually in forms like 'getAll(Collection keys)'). We can greatly speedup the 2nd-level caches by using these APIs (when available, of course).





I propose the following solutions:

1. I think it's possible to add a manual collection cache entry update in the postAction() callback. And it'll probably work.

2. This one is much harder to fix. I'm planning to add a special flag "onlyCached" to the LoadEvent and add the corresponding functionality to the DefaultLoadEventListener. So I'll have something like:
========
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
        throws HibernateException {
                Serializable[] array = ( Serializable[] ) disassembled;
                int size = array.length;
                Object [] loaded=new Object[size];
                List notInCache=new ArrayList();

                beforeInitialize( persister, size );

                for ( int i = 0; i < size; i++ ) {
                        loaded[i]=session.tryToLoadFromCache(array[i], owner);
                        if (loaded[i]==null)
                                notInCache.add(array[i]);
                }

                Iterator entities=getSession().createCriteria(
                        persister.getElementType().getName())
                        .add(Restrictions.in("id",notInCache))
                        .iterate();
                for(int i=0; i < size; i++)
                {
                        if (loaded[i]!=null)
                                list.add(loaded[i]);
                        else
                                list.add(entities.next());
                }
        }
========

3. This is a fairly large task, which requires changing some of Hibernate fundamentals (like LoadEvent). But I think I can do it.





Any thoughts? Am I stupidly missing some obvious flaw?


--
With respect,
            Alex Besogonov ([EMAIL PROTECTED])
_______________________________________________
hibernate-dev mailing list
hibernate-dev@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/hibernate-dev

Reply via email to