|
When a persistable class is persisted and has a container field (java.util.Collection or
java.util.Map) then DataNucleus needs to know when the user calls operations to change the
contents of the container. To do this, at the first reference to the container field once enlisted
in a transaction, DataNucleus will replace the container field with a
proxy wrapper
wrapping the real object. This has no effect for the user in that the field is still castable to
the same type as they had in that field, but all operations are intercepted.
By default when a container field is replaced by a second-class object (SCO) wrapper it will
be enabled to cache the values in that field. This means that once the values are loaded in
that field there will be no need to make any call to the datastore unless changing the
container. This gives significant speed ups when compared to relaying all calls via the
datastore. You can change to
not
use caching by setting either
-
Globally for the PersistenceManagerFactory - this is controlled by setting the PMF property
org.datanucleus.cache.collections
. Set it to false to pass through to the datastore.
-
For the specific Collection/Map - add a MetaData <collection> or <map> extension
cache
setting it to false to pass through to the datastore.
This is implemented in a typical SCO proxy wrapper by using the SCOUtils method
useContainerCache()
which determines if caching is required, and by having a method
load()
on all proxy wrapper container classes.
JDO and JPA provide mechanisms for specifying whether fields are loaded lazily (when required)
or whether they are loaded eagerly (when the object is first met). DataNucleus follows these
specifications but also allows the user to override the lazy loading for a SCO container. For
example if a collection field was marked as being part of the default fetch group it should be
loaded eagerly which means that when the owning object is instantiated the collection is
loaded up too. If the user overrides the lazy loading for that field in that situation to make
it lazy, DataNucleus will instantiate the owning object and instantiate the collection but
leave it marked as "to be loaded" and the elements will be loaded up when needed.
You can change the lazy loading setting via
-
Globally for the PersistenceManagerFactory - this is controlled by setting the PMF
property
org.datanucleus.cache.collections.lazy
. Set it to true to use lazy loading,
and set it to false to load the elements when the collection/map is initialised.
-
For the specific Collection/Map - add a MetaData <collection> or <map> extension
cache-lazy-loading
. Set it to true to use lazy loading, and false to load once at
initialisation.
When DataNucleus is using an optimistic transaction it attempts to delay all datastore operations
until
commit
is called on the transaction or
flush
is called on the
PersistenceManager/EntityManager. This implies a change to operation of SCO proxy wrappers
in that they must
queue
up all mutating operations (add, clear, remove etc) until
such a time as they need to be sent to the datastore. All SCO proxy wrappers have a List of
queued operations for this purpose.
All code for the actual queued operations are stored under
org.datanucleus.sco.queued
.
There are actually two sets of SCO wrappers in DataNucleus. The first set provide lazy loading,
queueing, etc etc. The second set are simple wrappers that intercept operations and mark the
field as dirty in the StateManager. This second set are for use with datastores such as
db4o
that don't utilise backing stores and just want to know when the field is dirty
and hence should be written.
All code for the simple SCO wrappers are stored under
org.datanucleus.sco.simple
.
|
|