Object-Relational
Mapping
Exposing
the
ORM
Cache
must be performed, or specifically when the user changes
the object and the implementation recognizes that the
copy must be made. An extension of that difficulty is that
the object changes cannot be made directly to the shared
object, but must instead be stored in the modifiable copy.
This presents the implementation with the burden of
having to return the changed state of the object when
accessed within the transaction while keeping those
changes isolated from other threads that may be accessing the shared object.
The most common technique for overcoming this
challenge is to weave the class at load time so that the
implementation can insert some proprietary handling
code into each and every instance that gets created. This
may or may not be palatable to some applications, but for
most modern-day systems that use aspect-oriented programming and numerous tools and libraries that exploit
the ability to perform bytecode weaving of some kind,
this does not end up being an onerous restriction. There
are, nevertheless, some obstacles that may still prevent
certain applications from using products that rely on
these kinds of techniques.
EXPLICIT COPY-BEFORE-WRITE
A third tactic to providing isolation in the face of transactional writes to objects is a twist on the previous copy-on-write, but balances the need to weave the object classes.
This approach is called explicit copy-before-write, precisely
because it requires the user to call into the ORM transactional manager to cause a copy to be made of a given
object. It benefits from the advantage offered by implicit
copy-on-write, in that only objects that are modified, or
explicitly copied, become transactional. A sample explicit
copy-before-write sequence would be:
1. Begin tx.
2. Read object (get object from shared cache or from
database).
4. User registers object copy in transaction (causing copy
to be inserted in tx cache).
5. User modifies object copy.
6. Tx commit begins.
7. Modified copy contents get sent to persistent storage.
8. Tx commit completes.
9. Changes made to object are merged into shared cache.
This example makes clear that the downside is that
users must either know up-front that they plan on modifying an object, or if they discover at some point in the
transaction that they need to modify a specific object,
then they must call for a copy to be made and begin with
a new version/instance of that object. In fact, it may have
even changed since the time it was previously read, so the
timing of when the copy is obtained can be important.
REFERENCE TIGHTENING
We can reduce the transactional-cache footprint by
incorporating the soft and weak referencing techniques
(described earlier in the context of the shared cache)
with the copying policies shown here. If we start with
weakly referenced objects, then as they become unused
or unreferenced they gradually become garbage-collected
and leave the cache over the course of longer-running
transactions.
The problem with weak objects in a transactional
cache, though, is that we run the risk of changing an
object and then moving on to another object, leaving
behind the one that we already changed. If it is weakly
referenced in the cache, then that object may fall out of
the cache and the changes will never get written out to
the backing database store. To prevent this from happening, the cache can tighten or strengthen the reference
from being weak to being hard at the point the change
is made. This will cause all objects containing changes
to be retained for the duration of the transaction, so no
changes will be lost, but unchanged objects that become
dereferenced will be permitted to fall out.
UNDERSTANDING THE OPTIONS
Caching in any system can be as simple or as complex
as the creator wants it to be, but the very nature of ORM
tools lends to them being a little more complex than the
average caching layer.
Despite the multitude of caching details that affect
the performance and semantics of the ORM runtime, the
goal does not need to be that every detail and nuance of
the implementation be known and understood. Having
a basic familiarity with the main issues and some of the
possible implementation choices provides the first line