3. Usage

3.1. How to activate Slice Runtime?
3.2. How to configure each database slice?
3.3. Implement DistributionPolicy interface
3.4. Implement ReplicationPolicy interface

Slice is activated via the following property settings:

3.1. How to activate Slice Runtime?

The basic configuration property is

 
         <property name="openjpa.BrokerFactory" value="slice"/>
       

This critical configuration activates a specialized object management kernel that can work against multiple databases.

3.2. How to configure each database slice?

Each database slice is identified by a logical name unique within a persistent unit. The list of the slices is specified by openjpa.slice.Names property. For example, specify three slices named "One", "Two" and "Three" as follows:

       <property name="openjpa.slice.Names" value="One, Two, Three"/>
      

This property is not mandatory. If this property is not specified then the configuration is scanned for logical slice names. Any property "abc" of the form openjpa.slice.XYZ.abc will register a slice with logical name "XYZ".

The order of the names is significant when no openjpa.slice.Master property is not specified. The persistence unit is then scanned to find all configured slice names and they are ordered alphabetically.

Each database slice properties can be configured independently. For example, the following configuration will register two slices with logical name One and Two.

 
        <property name="openjpa.slice.One.ConnectionURL" value="jdbc:mysql:localhost//slice1"/>
        <property name="openjpa.slice.Two.ConnectionURL" value="jdbc:mysql:localhost//slice2"/>
       

Any OpenJPA specific property can be configured per slice basis. For example, the following configuration will use two different JDBC drivers for slice One and Two.

 
        <property name="openjpa.slice.One.ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
        <property name="openjpa.slice.Two.ConnectionDriverName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
       

Any property if unspecified for a particular slice will be defaulted by corresponding OpenJPA property. For example, consider following three slices

 
         <property name="openjpa.slice.One.ConnectionURL"          value="jdbc:mysql:localhost//slice1"/>
         <property name="openjpa.slice.Two.ConnectionURL"          value="jdbc:mysql:localhost//slice2"/>
         <property name="openjpa.slice.Three.ConnectionURL"        value="jdbc:oracle:localhost//slice3"/>

         <property name="openjpa.ConnectionDriverName"     value="com.mysql.jdbc.Driver"/>
         <property name="openjpa.slice.Three.ConnectionDriverName" value="oracle.jdbc.Driver"/>
        

In this example, Three will use slice-specific oracle.jdbc.Driver driver while slice One and Two will use the driver com.mysql.jdbc.Driver as specified by openjpa.ConnectionDriverName property value.

A connection pool may also be used with Slice by using the openjpa.ConnectionProperties property. For example to use commons-dbcp with Derby you might use the following properties :

 
                <property name="openjpa.BrokerFactory" value="slice"/>
                <property name="openjpa.ConnectionDriverName" value="org.apache.commons.dbcp.BasicDataSource"/>
                <property name="openjpa.slice.Names" value="One,Two"/>
                <property name="openjpa.slice.Master" value="Two"/>
 
                <property name="openjpa.slice.One.ConnectionProperties" value="Url=jdbc:derby:target/database/openjpa-slice1;create=true, DriverClassName=org.apache.derby.jdbc.EmbeddedDriver"/>
                <property name="openjpa.slice.Two.ConnectionProperties" value="Url=jdbc:derby:target/database/openjpa-slice2;create=true, DriverClassName=org.apache.derby.jdbc.EmbeddedDriver"/>
 
                <property name="openjpa.jdbc.DBDictionary" value="derby"/>
            

Note

Be aware that you need to set the DBDictionary when using commons-dbcp.

3.3. Implement DistributionPolicy interface

Slice needs to determine which slice will persist a new instance. The application can only decide this policy (for example, all PurchaseOrders before April 30 goes to slice One, all the rest goes to slice Two). This is why the application has to implement org.apache.openjpa.slice.DistributionPolicy and specify the implementation class in configuration

 
          <property name="openjpa.slice.DistributionPolicy" value="com.acme.foo.MyOptimialDistributionPolicy"/>
        

The interface org.apache.openjpa.slice.DistributionPolicy is simple with a single method. The complete listing of the documented interface follows:

 
        
public interface DistributionPolicy {
    /**
     * Gets the name of the slice where a given instance will be stored.
     *  
     * @param pc The newly persistent or to-be-merged object. 
     * @param slices name of the configured slices.
     * @param context persistence context managing the given instance.
     * 
     * @return identifier of the slice. This name must match one of the
     * configured slice names. 
     * @see DistributedConfiguration#getSliceNames()
     */
    String distribute(Object pc, List<String> slices, Object context);
}

       

While implementing a distribution policy the most important thing to remember is collocation constraint. Because Slice can not establish or query any cross-database relationship, all the related instances must be stored in the same database slice. Slice can determine the closure of a root object by traversal of cascaded relationships. Hence user-defined policy has to only decide the database for the root instance that is the explicit argument to EntityManager.persist() call. Slice will ensure that all other related instances that get persisted by cascade are assigned to the same database slice as that of the root instance. However, the user-defined distribution policy must return the same slice identifier for the instances that are logically related but not cascaded for persist.

3.4. Implement ReplicationPolicy interface

The entities that are enumerated in openjpa.slice.ReplicatedTypes property can be stored in multiple slices as identical copies. Specify the implementation class of ReplicationPolicy in configuration as

 
          <property name="openjpa.slice.ReplicationPolicy" value="com.acme.foo.MyReplicationPolicy"/>