There are times when you need to replicate data between datastores. In many cases datastores themselves provide a means of doing this, however if you want to avoid using datastore-specific functionality you can utilise JDO to perform this task. JDO2 allows replication by use of detach/attach functionality. We demonstrate this with an example
public class ElementHolder
{
long id;
private Set elements = new HashSet();
...
}
public class Element
{
String name;
...
}
public class SubElement extends Element
{
double value;
...
}
so we have a 1-N unidirectional (Set) relation, and we define the metadata like this
<jdo>
<package name="org.apache.jdo.test">
<class name="ElementHolder" identity-type="application" detachable="true">
<inheritance strategy="new-table"/>
<field name="id" primary-key="true"/>
<field name="elements" persistence-modifier="persistent">
<collection element-type="Element"/>
<join/>
</field>
</class>
<class name="Element" identity-type="application" detachable="true">
<inheritance strategy="new-table"/>
<field name="name" primary-key="true"/>
</class>
<class name="SubElement">
<inheritance strategy="new-table"/>
<field name="value"/>
</class>
</package>
</jdo>
and so in our application we create some objects in datastore1, like this
PersistenceManagerFactory pmf1 = JDOHelper.getPersistenceManagerFactory("jdo.1.properties");
PersistenceManager pm1 = pmf1.getPersistenceManager();
Transaction tx1 = pm1.currentTransaction();
Object holderId = null;
try
{
tx1.begin();
ElementHolder holder = new ElementHolder(101);
holder.addElement(new Element("First Element"));
holder.addElement(new Element("Second Element"));
holder.addElement(new SubElement("First Inherited Element"));
holder.addElement(new SubElement("Second Inherited Element"));
pm1.makePersistent(holder);
tx1.commit();
holderId = JDOHelper.getObjectId(holder);
}
finally
{
if (tx1.isActive())
{
tx1.rollback();
}
pm1.close();
}
and now we want to replicate these objects into datastore2, so we detach them from datastore1 and attach them to datastore2, like this
// Detach the objects from "datastore1"
ElementHolder detachedHolder = null;
pm1 = pmf1.getPersistenceManager();
tx1 = pm1.currentTransaction();
try
{
pm1.getFetchPlan().setGroups(new String[] {FetchPlan.DEFAULT, FetchPlan.ALL});
pm1.getFetchPlan().setMaxFetchDepth(-1);
tx1.begin();
ElementHolder holder = (ElementHolder) pm1.getObjectById(holderID);
detachedHolder = (ElementHolder) pm1.detachCopy(holder);
tx1.commit();
}
finally
{
if (tx1.isActive())
{
tx1.rollback();
}
pm1.close();
}
// Attach the objects to datastore2
PersistenceManagerFactory pmf2 = JDOHelper.getPersistenceManagerFactory("jdo.2.properties");
PersistenceManager pm2 = pmf2.getPersistenceManager();
Transaction tx2 = pm2.currentTransaction();
try
{
tx2.begin();
pm2.makePersistent(detachedHolder);
tx2.commit();
}
finally
{
if (tx2.isActive())
{
tx2.rollback();
}
pm2.close();
}
These objects are now replicated into datastore2. Clearly you can extend this basic idea and replicate large amounts of data.