ObJectRelationalBridge
BRIDGING JAVA OBJECTS AND RELATIONAL DATABASES


the ojb object cache

Author: Thomas Mahler, september 2001

why a cache

OJB provides a simple Object Cache that holds Objects previously loaded or stored by the PersistenceBroker. Using a Cache has several advantages:

how it works

The OJB Cache provides the following interface to allow caching, lookup and removal of objects:

package ojb.broker.accesslayer;
public interface ObjectCache
{
    /**
     * Make object obj persistent to Objectcache.
     * compute objects identity and use it as key for the hashmap
     */
    public void cache(Object obj) throws ClassNotPersistenceCapableException;

    /**
     * makes object obj persistent to the Objectcache under the key oid.
     */
    public void cache(Identity oid, Object obj);

    /**
     * Lookup object with Identity oid in objectTable.
     * returns null if no matching id is found
     */
    public Object lookup(Identity oid);

    /**
     * removes an Object from the cache.
     */
    public void remove(Object obj);

    /**
     * clear the ObjectCache.
     */
    public void clear();
}

The OJB default implementation resides in the class ojb.broker.accesslayer.ObjectCacheDefaultImpl. This implementation uses a hashtable to hold all cached objects:

   private Hashtable objectTable = new Hashtable();

The Hashtable uses Identities as keys and object-references as values. For an example see the code of the .cache(...) method:

   public void cache(Identity oid, Object obj)
   {
        if (obj != null)
        {
            SoftReference ref = new SoftReference(obj);
            objectTable.put(oid.toString(), ref);
        }
   }

As you will have noticed, OJB uses SoftReferences. A SoftReference is not treated as a ordinary java reference. That is: if an object is not longer referenced by your application but only by the cache it can be reclaimed by the garbage collector (gc). The OJB cache does not provide its own memory management but lets the JVM gc do the job. Thus the lookup method has to take care if the gc did reclaim objects:

    public Object lookup(Identity oid)
    {
        Object obj = null;
        SoftReference ref = (SoftReference) objectTable.get(oid.toString());
        if (ref != null)
        {
            obj = ref.get();
            if (obj == null) // Soft-referenced Object reclaimed by GC !
            {
                objectTable.remove(oid);      
            }
        }
        return obj;
    }



implement your own cache

The OJB cache is quite simple but does a good job for most scenarios. If you need a more sophisticated cache (e.g. with MRU memory management strategies) you'll write your own implementation of the interface ojb.broker.accesslayer.ObjectCache. OJB provides a simple mechanism to integrate your implementation:

OJB obtains its cache instance from the factory ojb.broker.accesslayer.ObjectCacheFactory. This Factory can be configured to generate instances of your specific implementation by changing the following entry in the configuration file OJB.properties:

ObjectCacheClass=ojb.broker.accesslayer.ObjectCacheDefaultImpl

to:

ObjectCacheClass=acme.com.MyOwnObjectCache.

Of course I'm interested in your solutions! If you have implemented something interesting, just contact me.


$FOOTER$