mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#2377 - Wrong order in batch save, fix transaction depth
The guts of this fix is in DefaultPersister.saveAssocOne() with the change to use the new transaction.depthDecrement() method. For our failing test cases this changes the depth from -1, 0 to be 0, 1. We can see the impact of this change in the batch ordering via the logging of: io.ebean.SUM - txn[1001] BatchControl flush ...
This commit is contained in:
@@ -130,7 +130,7 @@ public interface SpiTransaction extends Transaction {
|
||||
Boolean getBatchGetGeneratedKeys();
|
||||
|
||||
/**
|
||||
* Modify and return the current 'depth' of the transaction.
|
||||
* Modify the current 'depth' of the transaction.
|
||||
* <p>
|
||||
* As we cascade save or delete we traverse the object graph tree. Going up
|
||||
* to Assoc Ones the depth decreases and going down to Assoc Manys the depth
|
||||
@@ -139,12 +139,31 @@ public interface SpiTransaction extends Transaction {
|
||||
* The depth is used for ordering batching statements. The lowest depth get
|
||||
* executed first during save.
|
||||
*/
|
||||
void depth(int diff);
|
||||
default void depth(int diff) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the depth BUT only if depth is greater than 0.
|
||||
* Return the amount that depth should be incremented by (0 or 1).
|
||||
*/
|
||||
default void depthDecrement() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the depth back to 0 - done at the end of top level insert and update.
|
||||
*/
|
||||
default void depthReset() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current depth.
|
||||
*/
|
||||
int depth();
|
||||
default int depth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if dirty beans are automatically persisted.
|
||||
|
||||
@@ -342,6 +342,16 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
|
||||
transaction.depth(diff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void depthDecrement() {
|
||||
transaction.depthDecrement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void depthReset() {
|
||||
transaction.depthReset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int depth() {
|
||||
return transaction.depth();
|
||||
|
||||
@@ -50,6 +50,13 @@ public abstract class PersistRequest extends BeanRequest implements BatchPostExe
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the transaction depth back to 0.
|
||||
*/
|
||||
public void resetDepth() {
|
||||
transaction.depthReset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTimingBatch(long startNanos, int size) {
|
||||
// nothing by default
|
||||
|
||||
@@ -251,6 +251,7 @@ public final class DefaultPersister implements Persister {
|
||||
} else {
|
||||
update(request);
|
||||
}
|
||||
request.resetDepth();
|
||||
}
|
||||
|
||||
draftHandler.updateDrafts(transaction, mgr);
|
||||
@@ -417,7 +418,7 @@ public final class DefaultPersister implements Persister {
|
||||
} else {
|
||||
update(req);
|
||||
}
|
||||
|
||||
req.resetDepth();
|
||||
req.commitTransIfRequired();
|
||||
req.flushBatchOnCascade();
|
||||
|
||||
@@ -455,6 +456,7 @@ public final class DefaultPersister implements Persister {
|
||||
try {
|
||||
req.initTransIfRequiredWithBatchCascade();
|
||||
insert(req);
|
||||
req.resetDepth();
|
||||
req.commitTransIfRequired();
|
||||
req.flushBatchOnCascade();
|
||||
|
||||
@@ -1123,7 +1125,7 @@ public final class DefaultPersister implements Persister {
|
||||
&& !prop.isReference(detailBean)
|
||||
&& !request.isParent(detailBean)) {
|
||||
SpiTransaction t = request.transaction();
|
||||
t.depth(-1);
|
||||
t.depthDecrement();
|
||||
saveRecurse(detailBean, t, null, request.flags());
|
||||
t.depth(+1);
|
||||
}
|
||||
|
||||
-12
@@ -232,18 +232,6 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
|
||||
throw new IllegalStateException(notExpectedMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void depth(int diff) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current depth.
|
||||
*/
|
||||
@Override
|
||||
public int depth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markNotQueryOnly() {
|
||||
}
|
||||
|
||||
@@ -484,34 +484,28 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
return existingBean.equals(beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the depth of the current persist request plus the diff. This has the
|
||||
* effect of changing the current depth and returning the new value. Pass
|
||||
* diff=0 to return the current depth.
|
||||
* <p>
|
||||
* The depth of 0 is for the initial persist request. It is modified as the
|
||||
* cascading of the save or delete traverses to the the associated Ones (-1)
|
||||
* and associated Manys (+1).
|
||||
* </p>
|
||||
* <p>
|
||||
* The depth is used to help the ordering of batched statements.
|
||||
* </p>
|
||||
*
|
||||
* @param diff the amount to add or subtract from the depth.
|
||||
*/
|
||||
@Override
|
||||
public final void depth(int diff) {
|
||||
depth += diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current depth.
|
||||
*/
|
||||
@Override
|
||||
public final int depth() {
|
||||
return depth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void depthDecrement() {
|
||||
if (depth != 0) {
|
||||
depth += -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void depthReset() {
|
||||
depth = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void markNotQueryOnly() {
|
||||
this.queryOnly = false;
|
||||
|
||||
@@ -310,15 +310,6 @@ final class NoTransaction implements SpiTransaction {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void depth(int diff) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int depth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExplicit() {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user