#2149 - Fix for ADD: jdbc batch flush doesnt execute sql statements created in lifecycle methods (e.g. beans saved in PostInsert etc)

Note that the foconis fork has a onPersist extension which is removed from the test.
This commit is contained in:
Robin Bygrave
2021-01-22 14:00:48 +13:00
parent 72331aa945
commit e38059f52c
4 changed files with 52 additions and 43 deletions
@@ -298,18 +298,7 @@ public final class BatchControl {
// Nothing in queue to flush
return;
}
// convert entry map to array for sorting
BatchedBeanHolder[] bsArray = getBeanHolderArray();
// sort the entries by depth
Arrays.sort(bsArray, depthComparator);
if (transaction.isLogSummary()) {
transaction.logSummary("BatchControl flush " + Arrays.toString(bsArray));
}
for (BatchedBeanHolder beanHolder : bsArray) {
beanHolder.executeNow();
}
executeAll();
persistedBeans.clear();
if (reset) {
beanHoldMap.clear();
@@ -323,6 +312,32 @@ public final class BatchControl {
}
}
private void executeAll() throws BatchedSqlException {
do {
// convert entry map to array for sorting
BatchedBeanHolder[] bsArray = getBeanHolderArray();
Arrays.sort(bsArray, depthComparator);
if (transaction.isLogSummary()) {
transaction.logSummary("BatchControl flush " + Arrays.toString(bsArray));
}
for (BatchedBeanHolder beanHolder : bsArray) {
beanHolder.executeNow();
}
} while (!isBeanHoldersEmpty());
}
/**
* Return if all bean holders are empty.
*/
private boolean isBeanHoldersEmpty() {
for (BatchedBeanHolder beanHolder : beanHoldMap.values()) {
if (!beanHolder.isEmpty()) {
return false;
}
}
return true;
}
/**
* Return an entry for the given type description. The type description is
* typically the bean class name (or table name for MapBeans).
@@ -47,6 +47,11 @@ class BatchedBeanHolder {
*/
private ArrayList<PersistRequest> deletes;
/**
* The holder is empty
*/
private boolean empty = true;
/**
* Create a new entry with a given type and depth.
*/
@@ -63,6 +68,13 @@ class BatchedBeanHolder {
return order;
}
/**
* Returns if the BeanHolder is empty.
*/
public boolean isEmpty() {
return empty;
}
/**
* Execute all the persist requests in this entry.
* <p>
@@ -90,6 +102,7 @@ class BatchedBeanHolder {
updates = new ArrayList<>();
control.executeNow(bufferedUpdates);
}
empty = true;
}
@Override
@@ -112,9 +125,8 @@ class BatchedBeanHolder {
* Add the request to the appropriate persist list.
*/
public int append(PersistRequestBean<?> request) {
empty = false;
request.setBatched();
switch (request.getType()) {
case INSERT:
if (inserts == null) {
@@ -11,7 +11,6 @@ import org.tests.model.basic.EBasicWithLog;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import io.ebean.Ebean;
public class TestLifecycleWithLog extends BaseTestCase {
@@ -31,22 +30,17 @@ public class TestLifecycleWithLog extends BaseTestCase {
bean.setName("Test1");
DB.save(bean);
assertThat(getLogs()).contains("onPersistTrigger", "prePersist", "postPersist");
assertThat(getLogs()).contains("prePersist", "postPersist");
bean.setName("Test2");
DB.save(bean);
assertThat(getLogs()).contains("onPersistTrigger", "preUpdate", "postUpdate");
assertThat(getLogs()).contains("preUpdate", "postUpdate");
DB.delete(bean);
assertThat(getLogs()).contains("onPersistTrigger", "preSoftDelete", "postSoftDelete");
assertThat(getLogs()).contains("preSoftDelete", "postSoftDelete");
DB.deletePermanent(bean);
assertThat(getLogs()).contains("onPersistTrigger", "preRemove", "postRemove");
assertThat(getLogs()).contains("preRemove", "postRemove");
}
@Test
@@ -59,22 +53,17 @@ public class TestLifecycleWithLog extends BaseTestCase {
List<EBasicWithLog> beans = Arrays.asList(bean);
DB.saveAll(beans);
assertThat(getLogs()).contains("prePersist", "postPersist");
assertThat(getLogs()).contains("onPersistTrigger", "prePersist", "postPersist");
bean.setName("Test2");
bean.setName("Test2Modified");
DB.saveAll(beans);
assertThat(getLogs()).contains("onPersistTrigger", "preUpdate", "postUpdate");
assertThat(getLogs()).contains("preUpdate", "postUpdate");
DB.deleteAll(beans);
assertThat(getLogs()).contains("onPersistTrigger", "preSoftDelete", "postSoftDelete");
assertThat(getLogs()).contains("preSoftDelete", "postSoftDelete");
DB.deleteAllPermanent(beans);
assertThat(getLogs()).contains("onPersistTrigger", "preRemove", "postRemove");
assertThat(getLogs()).contains("preRemove", "postRemove");
}
}
}
@@ -115,17 +115,10 @@ public class EBasicWithLog {
this.version = version;
}
public void _ebean_onPersistTrigger() {
writeLog("onPersistTrigger");
}
/**
* @param string
*/
private void writeLog(String title) {
EBasicLog log = new EBasicLog();
log.setName(title);
DB.save(log);
}
}
}