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

    1. public class ElementHolder
    2. {
    3. long id;
    4. private Set elements = new HashSet();
    5. ...
    6. }
    7. public class Element
    8. {
    9. String name;
    10. ...
    11. }
    12. public class SubElement extends Element
    13. {
    14. double value;
    15. ...
    16. }

    so we have a 1-N unidirectional (Set) relation, and we define the metadata like this

    1. <jdo>
    2. <package name="org.apache.jdo.test">
    3. <class name="ElementHolder" identity-type="application" detachable="true">
    4. <inheritance strategy="new-table"/>
    5. <field name="id" primary-key="true"/>
    6. <field name="elements" persistence-modifier="persistent">
    7. <collection element-type="Element"/>
    8. <join/>
    9. </field>
    10. </class>
    11. <class name="Element" identity-type="application" detachable="true">
    12. <inheritance strategy="new-table"/>
    13. <field name="name" primary-key="true"/>
    14. </class>
    15. <class name="SubElement">
    16. <inheritance strategy="new-table"/>
    17. <field name="value"/>
    18. </class>
    19. </package>
    20. </jdo>

    and so in our application we create some objects in datastore1, like this

    1. PersistenceManagerFactory pmf1 = JDOHelper.getPersistenceManagerFactory("jdo.1.properties");
    2. PersistenceManager pm1 = pmf1.getPersistenceManager();
    3. Transaction tx1 = pm1.currentTransaction();
    4. Object holderId = null;
    5. try
    6. {
    7. tx1.begin();
    8. ElementHolder holder = new ElementHolder(101);
    9. holder.addElement(new Element("First Element"));
    10. holder.addElement(new Element("Second Element"));
    11. holder.addElement(new SubElement("First Inherited Element"));
    12. holder.addElement(new SubElement("Second Inherited Element"));
    13. pm1.makePersistent(holder);
    14. tx1.commit();
    15. holderId = JDOHelper.getObjectId(holder);
    16. }
    17. finally
    18. {
    19. if (tx1.isActive())
    20. {
    21. tx1.rollback();
    22. }
    23. pm1.close();
    24. }

    and now we want to replicate these objects into datastore2, so we detach them from datastore1 and attach them to datastore2, like this

    1. // Detach the objects from "datastore1"
    2. ElementHolder detachedHolder = null;
    3. pm1 = pmf1.getPersistenceManager();
    4. tx1 = pm1.currentTransaction();
    5. try
    6. {
    7. pm1.getFetchPlan().setGroups(new String[] {FetchPlan.DEFAULT, FetchPlan.ALL});
    8. pm1.getFetchPlan().setMaxFetchDepth(-1);
    9. tx1.begin();
    10. ElementHolder holder = (ElementHolder) pm1.getObjectById(holderID);
    11. detachedHolder = (ElementHolder) pm1.detachCopy(holder);
    12. tx1.commit();
    13. }
    14. finally
    15. {
    16. if (tx1.isActive())
    17. {
    18. tx1.rollback();
    19. }
    20. pm1.close();
    21. }
    22. // Attach the objects to datastore2
    23. PersistenceManagerFactory pmf2 = JDOHelper.getPersistenceManagerFactory("jdo.2.properties");
    24. PersistenceManager pm2 = pmf2.getPersistenceManager();
    25. Transaction tx2 = pm2.currentTransaction();
    26. try
    27. {
    28. tx2.begin();
    29. pm2.makePersistent(detachedHolder);
    30. tx2.commit();
    31. }
    32. finally
    33. {
    34. if (tx2.isActive())
    35. {
    36. tx2.rollback();
    37. }
    38. pm2.close();
    39. }

    These objects are now replicated into datastore2. Clearly you can extend this basic idea and replicate large amounts of data.