I poked around a bit, but couldn't find an answer to the question I have.
I have an entity that involves a one-to-many relationship - an order is the parent, and an order can be served by multiple shipments. This entity is stored in two separate databases.
One database is the one that will receive updates from various sources. I'll call it sourceDB from here on. The other database gets a subset of the entries in the primary database, ones that, for whatever reason, I'm interested in tracking / doing more work on without mucking with the sourceDB. We'll call this one workDB.
I have java code to select out the entities I want to move across from sourceDB to workDB, and actually perform the replication. That code looks something like this:
Code:
/* The collection of orders comes from a method that loads from sourceDB, and forces the lazy loading so that all children for a parent should be available for replication */
static public void replicateEntries( SessionFactory toSession,
Collection<Order> orders )
{
Session session = null ;
Transaction tx = null;
try {
session = toSession.openSession() ;
// copy orders over.
for( Order order : orders )
{
try {
tx = session.beginTransaction() ;
session.replicate( order, ReplicationMode.OVERWRITE ) ;
tx.commit();
tx = null;
} catch( HibernateException e) {
System.err.println( "Order " + order.getId() + " with ref " + order.getOrderReferenceId() + " caused a replication error." );
System.err.println( "The hibernate error was " + e );
e.printStackTrace();
} finally {
if( tx != null )
tx.rollback();
}
}
} finally {
if( session != null )
session.close();
}
}
The definition of Order includes the following:
Code:
<set
name="Shipments"
inverse=true
cascade="all, delete_orphan"
lazy="true"
fetch="select">
<key column="ORDER_ID"/>
<one-to-many class="Shipment">
</set>
Now, if you've read this far, I'm sure you're curious about the problem. Replicate is working great when an order first appears at the source and moves across for the first time - the associated shipments get moved fine. If I add a shipment to an open order, or order information changes, this gets updated in workDB without a problem. The problem is when a shipment is removed from an order in the sourceDB - replication does
not remove the shipment in the workDB.
I currently have a workaround involving an explicit (cascading) delete on the entity in workDB, followed by the replication call as presented. That works fine, but is needlessly slow. I'm sure I could also workaround by poking through the Shipments in WorkDB, comparing them to the children of the loaded Order, and explicitly replicating/deleting those. However, it seems to me that replicate on the parent entity, with the cascade set to all should take care of this chore of updating/creating/removing children as necessary.
Please let me know if I'm doing something obviously wrong, have poor expectation/understanding of what replicate() does, or you can't decide because I've forgotten to include some important piece of code/schema.
Thanks for reading, and thanks in advance for your answers.