* @since 1.2
*/
GraphDiff flushToParent(boolean cascade) {
if (this.getChannel() == null) {
throw new CayenneRuntimeException(
"Cannot commit changes - channel is not set.");
}
int syncType = cascade
? DataChannel.FLUSH_CASCADE_SYNC
: DataChannel.FLUSH_NOCASCADE_SYNC;
// prevent multiple commits occuring simulteneously
synchronized (getObjectStore()) {
DataContextFlushEventHandler eventHandler = null;
ObjectStoreGraphDiff changes = getObjectStore().getChanges();
boolean noop = isValidatingObjectsOnCommit()
? changes.validateAndCheckNoop()
: changes.isNoop();
if (noop) {
// need to clear phantom changes
getObjectStore().postprocessAfterPhantomCommit();
return new CompoundDiff();
}
if (isTransactionEventsEnabled()) {
eventHandler = new DataContextFlushEventHandler(this);
eventHandler.registerForDataContextEvents();
fireWillCommit();
}
try {
GraphDiff returnChanges = getChannel().onSync(this, changes, syncType);
getObjectStore().postprocessAfterCommit(returnChanges);
// this is a legacy event ... will deprecate in 2.0
fireTransactionCommitted();
// this event is caught by peer nested DataContexts to synchronize the
// state
fireDataChannelCommitted(this, changes);
// this event is caught by child DataContexts to update temporary
// ObjectIds with permanent
if (!returnChanges.isNoop()) {
fireDataChannelCommitted(getChannel(), returnChanges);
}
return returnChanges;
}
// "catch" is needed to unwrap OptimisticLockExceptions
catch (CayenneRuntimeException ex) {
fireTransactionRolledback();
Throwable unwound = Util.unwindException(ex);
if (unwound instanceof CayenneRuntimeException) {
throw (CayenneRuntimeException) unwound;
}
else {
throw new CayenneRuntimeException("Commit Exception", unwound);
}
}
finally {
if (isTransactionEventsEnabled()) {