The existing application or the persistent domain model requires no change to upgrade from a single database to a distributed database environment.
User application decides how the newly persistent instances be distributed across the database slices. The data distribution policy across the slices may be based on the attribute of the data itself. For example, all Customer whose first name begins with character 'A' to 'M' will be stored in one slice while names beginning with 'N' to 'Z' will be stored in another slice.
This custom data distribution policy is specified by implementing
org.apache.openjpa.slice.DistributionPolicy
interface by the user application.
Slice tracks the original database for existing instances. When an application issues a query, the resultant instances can be loaded from different slices. This tracking is important as subsequent update to any of these instances is committed to the appropriate original database slice.
You can find the original slice of an instance pc
by
the static utility method
SlicePersistence.getSlice(pc)
.
This method returns the slice identifier string associated with the
given managed instance. If the instance is not
being managed then the method return null because any unmanaged or
detached instance is not associated with any slice.
Each slice can be configured independently with its own JDBC driver and other connection parameters. Hence the target database environment can constitute of heterogeneous databases.
All database operations such as query, commit or flush operates in parallel across the database slices. The execution threading policy is configurable.
The queries are executed across all slices and the results are
merged into a single list. The query result that includes
ORDER BY
clause are sorted correctly by merging
results from each individual slice.
COUNT()
, MAX()
, MIN()
and SUM()
are correctly evaluated only if they
return a single result.
AVG()
is not supported.
You can target the query only to a subset of slices rather than
all slices by setting a hint. The hint key
openjpa.hint.slice.Target
is set on any query and
hint value is
comma-separated list of slice identifiers. The following
example shows how to target a query only to slice "One"
EntityManager em = ...; em.getTransaction().begin(); String hint = "openjpa.hint.slice.Target"; Query query = em.createQuery("SELECT p FROM PObject").setHint(hint, "One"); List result = query.getResultList(); // verify that each instance is originaing from the given slice for (Object pc : result) { String sliceOrigin = SlicePersistence.getSlice(pc); assertTrue ("One", sliceOrigin); }
The database slices participate in a global transaction provided
each slice is configured with a XA-compliant JDBC driver, even
when the persistence unit is configured for RESOURCE_LOCAL
transaction.
RESOURCE_LOCAL
transaction then each slice is committed without any two-phase
commit protocol. If commit on any slice fails, then atomic nature of
the transaction is not ensured.
No relationship can exist across database slices. In O-R mapping parlance, this condition translates to the limitation that the closure of an object graph must be collocated in the same database. For example, consider a domain model where Person relates to Adress. Person X refers to Address A while Person Y refers to Address B. Collocation Constraint means that both X and A must be stored in the same database slice. Similarly Y and B must be stored in a single slice.
Slice, however, helps to maintain collocation constraint automatically. The instances in the closure set of any newly persistent instance reachable via cascaded relationship is stored in the same slice. The user-defined distribution policy requires to supply the slice for the root instance only.