mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
FIX: Recursive batch flush can save dependant beans in wrong order
This commit is contained in:
committed by
Roland Praml
parent
83e87b0c67
commit
d3427876b7
@@ -224,14 +224,21 @@ public final class BatchControl {
|
||||
* Execute all the requests contained in the list.
|
||||
*/
|
||||
void executeNow(ArrayList<PersistRequest> list) throws BatchedSqlException {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (i % batchSize == 0) {
|
||||
// hit the batch size so flush
|
||||
flushPstmtHolder();
|
||||
boolean old = transaction.isFlushOnQuery();
|
||||
transaction.setFlushOnQuery(false);
|
||||
// disable flush on query due transsaction callbacks
|
||||
try {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (i % batchSize == 0) {
|
||||
// hit the batch size so flush
|
||||
flushPstmtHolder();
|
||||
}
|
||||
list.get(i).executeNow();
|
||||
}
|
||||
list.get(i).executeNow();
|
||||
flushPstmtHolder();
|
||||
} finally {
|
||||
transaction.setFlushOnQuery(old);
|
||||
}
|
||||
flushPstmtHolder();
|
||||
}
|
||||
|
||||
public void flushOnCommit() throws BatchedSqlException {
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
package org.tests.batchinsert;
|
||||
|
||||
import io.ebean.*;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.xtest.IgnorePlatform;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.Transactional;
|
||||
import io.ebean.meta.MetaTimedMetric;
|
||||
import io.ebean.meta.ServerMetrics;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.xtest.IgnorePlatform;
|
||||
import io.ebean.xtest.base.DtoQuery2Test;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
import org.tests.model.basic.TSDetail;
|
||||
import org.tests.model.basic.TSMaster;
|
||||
import org.tests.model.basic.*;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -25,6 +25,38 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class TestBatchInsertFlush extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void batchFlush() {
|
||||
|
||||
TSMaster m = new TSMaster();
|
||||
m.setName("master1");
|
||||
DB.save(m);
|
||||
DB.getDefault().cacheManager().clearAll();
|
||||
|
||||
try (Transaction txn = DB.beginTransaction()) {
|
||||
txn.setBatchSize(2);
|
||||
txn.setBatchMode(true);
|
||||
|
||||
List<Customer> customers = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Customer customer = ResetBasicData.createCustomer("BatchFlushPreInsert " + i, null, null, 3);
|
||||
customer.addContact(new Contact("Fred" + i, "Blue"));
|
||||
customers.add(customer);
|
||||
}
|
||||
|
||||
for (int i = 3; i < 6; i++) {
|
||||
Customer customer = ResetBasicData.createCustomer("BatchFlushPostInsert " + i, null, null, 3);
|
||||
customer.addContact(new Contact("Fred" + i, "Blue"));
|
||||
customers.add(customer);
|
||||
}
|
||||
|
||||
DB.saveAll(customers);
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void no_cascade() {
|
||||
|
||||
@@ -70,7 +102,7 @@ public class TestBatchInsertFlush extends BaseTestCase {
|
||||
// detail
|
||||
assertThat(sql.get(3)).contains("insert into t_detail_with_other_namexxxyy");
|
||||
|
||||
assertThat(((SpiTransaction)transaction).label()).isEqualTo("TestBatchInsertFlush.no_cascade");
|
||||
assertThat(((SpiTransaction) transaction).label()).isEqualTo("TestBatchInsertFlush.no_cascade");
|
||||
|
||||
} finally {
|
||||
transaction.end();
|
||||
@@ -133,7 +165,7 @@ public class TestBatchInsertFlush extends BaseTestCase {
|
||||
|
||||
// trigger JDBC batch by default
|
||||
DB.findDto(DtoQuery2Test.DCust.class, "select id, name from o_customer")
|
||||
.findList();
|
||||
.findList();
|
||||
|
||||
List<String> sql = LoggedSql.stop();
|
||||
assertSql(sql.get(0)).contains("insert into e_basicver");
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package org.tests.model.basic.event;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.event.BeanPersistAdapter;
|
||||
import io.ebean.event.BeanPersistRequest;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.TSMaster;
|
||||
|
||||
public class CustomerPersistAdapter extends BeanPersistAdapter {
|
||||
|
||||
@@ -16,7 +18,9 @@ public class CustomerPersistAdapter extends BeanPersistAdapter {
|
||||
|
||||
// StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
// request.getTransaction().log("+++++ "+Arrays.toString(stackTrace));
|
||||
|
||||
if (((Customer) request.bean()).getName().startsWith("BatchFlushPreInsert")) {
|
||||
DB.find(TSMaster.class).where().eq("name", "master1").exists();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -28,4 +32,11 @@ public class CustomerPersistAdapter extends BeanPersistAdapter {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postInsert(BeanPersistRequest<?> request) {
|
||||
super.postInsert(request);
|
||||
if (((Customer) request.bean()).getName().startsWith("BatchFlushPostInsert")) {
|
||||
DB.find(TSMaster.class).where().eq("name", "master1").exists();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user