diff --git a/pom.xml b/pom.xml
index 4ea495c50..e58258676 100644
--- a/pom.xml
+++ b/pom.xml
@@ -174,7 +174,7 @@
org.avaje.ebeanorm
avaje-ebeanorm-agent
- 4.11.1
+ 4.12.1-SNAPSHOT
test
@@ -249,7 +249,7 @@
org.avaje.ebeanorm
avaje-ebeanorm-mavenenhancer
- 4.11.1
+ 4.12.1-SNAPSHOT
test
diff --git a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
index 24462e614..1f9af8aa9 100644
--- a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
+++ b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
@@ -39,6 +39,8 @@ public final class EntityBeanIntercept implements Serializable {
private transient BeanLoader beanLoader;
+ private transient PreGetterCallback preGetterCallback;
+
private String ebeanServerName;
/**
@@ -186,6 +188,21 @@ public final class EntityBeanIntercept implements Serializable {
return embeddedOwnerIndex;
}
+ /**
+ * Clear the getter callback.
+ */
+ public void clearGetterCallback() {
+ this.preGetterCallback = null;
+ }
+
+ /**
+ * Register the callback to be triggered when getter is called.
+ * This is used primarily to automatically flush the JDBC batch.
+ */
+ public void registerGetterCallback(PreGetterCallback getterCallback) {
+ this.preGetterCallback = getterCallback;
+ }
+
/**
* Set the embedded beans owning bean.
*/
@@ -832,19 +849,31 @@ public final class EntityBeanIntercept implements Serializable {
public void initialisedMany(int propertyIndex) {
loadedProps[propertyIndex] = true;
}
-
+
+ private final void preGetterCallback() {
+ if (preGetterCallback != null) {
+ preGetterCallback.preGetterTrigger();
+ }
+ }
+
+ /**
+ * Called prior to Id property getter.
+ */
+ public void preGetId() {
+ preGetterCallback();
+ }
+
/**
* Method that is called prior to a getter method on the actual entity.
*/
public void preGetter(int propertyIndex) {
+ preGetterCallback();
if (state == STATE_NEW || disableLazyLoad) {
return;
}
-
if (!isLoadedProperty(propertyIndex)) {
loadBean(propertyIndex);
}
-
if (nodeUsageCollector != null) {
nodeUsageCollector.addUsed(getProperty(propertyIndex));
}
diff --git a/src/main/java/com/avaje/ebean/bean/PreGetterCallback.java b/src/main/java/com/avaje/ebean/bean/PreGetterCallback.java
new file mode 100644
index 000000000..8faecec22
--- /dev/null
+++ b/src/main/java/com/avaje/ebean/bean/PreGetterCallback.java
@@ -0,0 +1,13 @@
+package com.avaje.ebean.bean;
+
+/**
+ * A callback that can be registered to fire on getter method calls.
+ * It's primary purpose is to automatically flush JDBC batch buffer.
+ */
+public interface PreGetterCallback {
+
+ /**
+ * Trigger the callback.
+ */
+ void preGetterTrigger();
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
index afd86bfa6..55c997538 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
@@ -1,6 +1,7 @@
package com.avaje.ebeaninternal.server.core;
import com.avaje.ebean.ValuePair;
+import com.avaje.ebean.bean.PreGetterCallback;
import com.avaje.ebeaninternal.api.ConcurrencyMode;
import com.avaje.ebean.annotation.DocStoreMode;
import com.avaje.ebean.bean.EntityBean;
@@ -36,7 +37,7 @@ import java.util.Set;
/**
* PersistRequest for insert update or delete of a bean.
*/
-public final class PersistRequestBean extends PersistRequest implements BeanPersistRequest, DocStoreUpdate {
+public final class PersistRequestBean extends PersistRequest implements BeanPersistRequest, DocStoreUpdate, PreGetterCallback {
private final BeanManager beanManager;
@@ -137,6 +138,11 @@ public final class PersistRequestBean extends PersistRequest implements BeanP
private long version;
+ /**
+ * Flag set when request is added to JDBC batch registered as a "getter callback" to automatically flush batch.
+ */
+ private boolean getterCallback;
+
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager mgr, SpiTransaction t,
PersistExecute persistExecute, PersistRequest.Type type, boolean saveRecurse, boolean publish) {
@@ -239,8 +245,17 @@ public final class PersistRequestBean extends PersistRequest implements BeanP
*/
public void setBatched() {
batched = true;
+ if (type == Type.INSERT || type == Type.UPDATE) {
+ // used to trigger automatic jdbc batch flush
+ intercept.registerGetterCallback(this);
+ getterCallback = true;
+ }
}
+ @Override
+ public void preGetterTrigger() {
+ transaction.flushBatch();
+ }
public void setSkipBatchForTopLevel() {
skipBatchForTopLevel = true;
@@ -621,6 +636,9 @@ public final class PersistRequestBean extends PersistRequest implements BeanP
@Override
public int executeNow() {
+ if (getterCallback) {
+ intercept.clearGetterCallback();
+ }
switch (type) {
case INSERT:
persistExecute.executeInsertBean(this);
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java
index 0a3f05474..aa677d98b 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java
@@ -217,12 +217,10 @@ public final class IdBinderSimple implements IdBinder {
if (!idValue.getClass().equals(expectedType)) {
idValue = scalarType.toBeanType(idValue);
}
-
if (bean != null) {
// support PropertyChangeSupport
idProperty.setValueIntercept(bean, idValue);
}
-
return idValue;
}
}
diff --git a/src/test/java/com/avaje/tests/batchinsert/TestBatchInsertFlush.java b/src/test/java/com/avaje/tests/batchinsert/TestBatchInsertFlush.java
index ed5fc8892..141da0b3c 100644
--- a/src/test/java/com/avaje/tests/batchinsert/TestBatchInsertFlush.java
+++ b/src/test/java/com/avaje/tests/batchinsert/TestBatchInsertFlush.java
@@ -10,6 +10,8 @@ import org.junit.Test;
import java.sql.Timestamp;
+import static org.junit.Assert.assertNotNull;
+
public class TestBatchInsertFlush extends BaseTestCase {
@Test
@@ -26,12 +28,8 @@ public class TestBatchInsertFlush extends BaseTestCase {
EBasicVer b2 = new EBasicVer("b2");
server.save(b2, txn);
- //txn.flushBatch();
-
- b1.setDescription("modify");
- System.out.println("here");
- Timestamp lastUpdate = b1.getLastUpdate();
Integer id = b1.getId();
+ assertNotNull(id);
EBasicVer b3 = new EBasicVer("b3");
server.save(b3, txn);
@@ -41,7 +39,60 @@ public class TestBatchInsertFlush extends BaseTestCase {
} finally {
txn.end();
}
+ }
+ @Test
+ public void testFlushOnGetProperty() {
+ EbeanServer server = Ebean.getDefaultServer();
+ Transaction txn = server.beginTransaction();
+ try {
+ txn.setBatch(PersistBatch.ALL);
+
+ EBasicVer b1 = new EBasicVer("b1");
+ server.save(b1, txn);
+
+ EBasicVer b2 = new EBasicVer("b2");
+ server.save(b2, txn);
+
+ // flush here
+ Timestamp lastUpdate = b1.getLastUpdate();
+ assertNotNull(lastUpdate);
+
+ EBasicVer b3 = new EBasicVer("b3");
+ server.save(b3, txn);
+
+ txn.commit();
+
+ } finally {
+ txn.end();
+ }
+ }
+
+ @Test
+ public void testFlushOnSetProperty() {
+
+ EbeanServer server = Ebean.getDefaultServer();
+ Transaction txn = server.beginTransaction();
+ try {
+ txn.setBatch(PersistBatch.ALL);
+
+ EBasicVer b1 = new EBasicVer("b1");
+ server.save(b1, txn);
+
+ EBasicVer b2 = new EBasicVer("b2");
+ server.save(b2, txn);
+
+ // flush here
+ b1.setDescription("modify");
+
+ EBasicVer b3 = new EBasicVer("b3");
+ server.save(b3, txn);
+
+ txn.commit();
+
+ } finally {
+ txn.end();
+ }
}
}
diff --git a/src/test/java/com/avaje/tests/model/basic/xtra/TestInsertBatchThenUpdate.java b/src/test/java/com/avaje/tests/model/basic/xtra/TestInsertBatchThenUpdate.java
index 617cc1e95..a9c22e64c 100644
--- a/src/test/java/com/avaje/tests/model/basic/xtra/TestInsertBatchThenUpdate.java
+++ b/src/test/java/com/avaje/tests/model/basic/xtra/TestInsertBatchThenUpdate.java
@@ -10,6 +10,7 @@ import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
public class TestInsertBatchThenUpdate extends BaseTestCase {
@@ -24,6 +25,8 @@ public class TestInsertBatchThenUpdate extends BaseTestCase {
try {
txn.setBatch(PersistBatch.ALL);
+ LoggedSqlCollector.start();
+
EdParent parent = new EdParent();
parent.setName("MyComputer");
@@ -36,21 +39,17 @@ public class TestInsertBatchThenUpdate extends BaseTestCase {
Ebean.save(parent);
- // nothing flushed yet
- List loggedSql0 = LoggedSqlCollector.start();
- assertEquals(0, loggedSql0.size());
-
parent.setName("MyDesk");
Ebean.save(parent);
- // nothing flushed yet
- assertEquals(0, LoggedSqlCollector.start().size());
-
Ebean.commitTransaction();
// insert statements for EdExtendedParent
- List loggedSql2 = LoggedSqlCollector.start();
- assertEquals(2, loggedSql2.size());
+ List loggedSql = LoggedSqlCollector.stop();
+ assertEquals(3, loggedSql.size());
+ assertThat(loggedSql.get(0)).contains("insert into td_parent");
+ assertThat(loggedSql.get(1)).contains("insert into td_child ");
+ assertThat(loggedSql.get(2)).contains("update td_parent set parent_name=? where parent_id=?");
} finally {
Ebean.endTransaction();