diff --git a/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java b/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java index d71d7e9cd..9a8d0f23b 100644 --- a/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java +++ b/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java @@ -1307,14 +1307,22 @@ public final class PersistRequestBean extends PersistRequest implements BeanP * Set the request flags indicating this is an insert. */ public void flagInsert() { - flags = Flags.setInsert(flags); + if (intercept.isNew()) { + flags = Flags.setInsertNormal(flags); + } else { + flags = Flags.setInsert(flags); + } } /** * Unset the request insert flag indicating this is an update. */ public void flagUpdate() { - flags = Flags.unsetInsert(flags); + if (intercept.isLoaded()) { + flags = Flags.setUpdateNormal(flags); + } else { + flags = Flags.setUpdate(flags); + } } /** diff --git a/src/main/java/io/ebeaninternal/server/persist/DefaultPersister.java b/src/main/java/io/ebeaninternal/server/persist/DefaultPersister.java index feb7337b3..0e402dcdc 100644 --- a/src/main/java/io/ebeaninternal/server/persist/DefaultPersister.java +++ b/src/main/java/io/ebeaninternal/server/persist/DefaultPersister.java @@ -456,8 +456,7 @@ public final class DefaultPersister implements Persister { void saveRecurse(EntityBean bean, Transaction t, Object parentBean, int flags) { // determine insert or update taking into account stateless updates - PersistRequestBean request = createRequestRecurse(bean, t, parentBean, flags); - saveRecurse(request); + saveRecurse(createRequestRecurse(bean, t, parentBean, flags)); } private void saveRecurse(PersistRequestBean request) { @@ -1229,8 +1228,8 @@ public final class DefaultPersister implements Persister { BeanDescriptor desc = mgr.getBeanDescriptor(); EntityBean entityBean = (EntityBean) bean; PersistRequest.Type type; - if (Flags.isPublishOrMerge(flags)) { - // insert if it is a new bean (as publish created it) + if (Flags.isPublishMergeOrNormal(flags)) { + // just use bean state to determine insert or update type = entityBean._ebean_getIntercept().isUpdate() ? Type.UPDATE : Type.INSERT; } else { // determine Insert or Update based on bean state and insert flag diff --git a/src/main/java/io/ebeaninternal/server/persist/Flags.java b/src/main/java/io/ebeaninternal/server/persist/Flags.java index ffde410c5..263dbb6e8 100644 --- a/src/main/java/io/ebeaninternal/server/persist/Flags.java +++ b/src/main/java/io/ebeaninternal/server/persist/Flags.java @@ -5,7 +5,7 @@ package io.ebeaninternal.server.persist; *

* Allows passing of flag state when recursively persisting. */ -public class Flags { +public final class Flags { /** * Indicates the bean is being inserted. @@ -27,6 +27,11 @@ public class Flags { */ public static final int MERGE = 0x00000008; + /** + * Indicates Normal insert or update (not forced). + */ + public static final int NORMAL = 0x00000010; + /** * No flags set. */ @@ -34,7 +39,9 @@ public class Flags { public static final int PUBLISH_RECURSE = PUBLISH + RECURSE; - private static final int PUBLISH_MERGE = PUBLISH + MERGE; + private static final int PUBLISH_MERGE_NORMAL = PUBLISH + MERGE + NORMAL; + + private static final int INSERT_NORMAL = INSERT + NORMAL; /** * Return true if the bean is being inserted. @@ -65,10 +72,10 @@ public class Flags { } /** - * Return true if part of a Merge or Publish. + * Return true if part of a Merge or Publish or Normal (bean state matches persist). */ - public static boolean isPublishOrMerge(long state) { - return (state & PUBLISH_MERGE) != 0; + public static boolean isPublishMergeOrNormal(int state) { + return (state & PUBLISH_MERGE_NORMAL) != 0; } /** @@ -82,54 +89,70 @@ public class Flags { * Set Insert flag. */ public static int setInsert(int state) { - return set(state, INSERT, true); + return set(state, INSERT); + } + + /** + * Insert flag and normal in that bean is in NEW state (for insert). + */ + public static int setInsertNormal(int state) { + return set(state, INSERT_NORMAL); } /** * Parent was not inserted. */ - public static int unsetInsert(int state) { - return set(state, INSERT, false); + public static int setUpdate(int state) { + return unset(state, INSERT); + } + + /** + * Not Insert and normal in that bean is in LOADED state (for update). + */ + public static int setUpdateNormal(int state) { + state &= ~INSERT; + state |= NORMAL; + return state; } /** * Set Recurse flag. */ public static int setRecurse(int state) { - return set(state, RECURSE, true); + return set(state, RECURSE); } public static int unsetRecuse(int state) { - return set(state, RECURSE, false); + return unset(state, RECURSE); } /** * Set Publish flag. */ public static int setPublish(int state) { - return set(state, PUBLISH, true); + return set(state, PUBLISH); } public static int unsetPublish(int state) { - return set(state, PUBLISH, false); + return unset(state, PUBLISH); } /** * Set Merge flag. */ public static int setMerge(int state) { - return set(state, MERGE, true); + return set(state, MERGE); } public static int unsetMerge(int state) { - return set(state, MERGE, false); + return unset(state, MERGE); } - private static int set(int state, int flag, boolean setFlag) { - if (setFlag) { - return (state |= flag); - } else { - return state &= ~flag; - } + private static int set(int state, int flag) { + return (state |= flag); + } + + private static int unset(int state, int flag) { + return state &= ~flag; } } diff --git a/src/test/java/io/ebeaninternal/server/persist/FlagsTest.java b/src/test/java/io/ebeaninternal/server/persist/FlagsTest.java index 4e4d947c4..0753a3841 100644 --- a/src/test/java/io/ebeaninternal/server/persist/FlagsTest.java +++ b/src/test/java/io/ebeaninternal/server/persist/FlagsTest.java @@ -26,19 +26,60 @@ public class FlagsTest { assertThat(Flags.isSet(state, Flags.PUBLISH)).isFalse(); assertThat(Flags.isSet(state, Flags.MERGE)).isTrue(); assertThat(Flags.isSet(state, Flags.INSERT)).isTrue(); + } + @Test + public void insert() { + + int state = 0; + + state = Flags.setInsert(state); + assertThat(Flags.isSet(state, Flags.INSERT)).isTrue(); + assertThat(Flags.isSet(state, Flags.NORMAL)).isFalse(); + } + + @Test + public void insertNormal() { + + int state = 0; + + state = Flags.setInsertNormal(state); + assertThat(Flags.isSet(state, Flags.INSERT)).isTrue(); + assertThat(Flags.isSet(state, Flags.NORMAL)).isTrue(); + } + + @Test + public void update() { + + int state = 0; + + state = Flags.setUpdate(state); + assertThat(Flags.isSet(state, Flags.INSERT)).isFalse(); + assertThat(Flags.isSet(state, Flags.NORMAL)).isFalse(); + } + + @Test + public void updateNormal() { + + int state = 0; + + state = Flags.setUpdateNormal(state); + assertThat(Flags.isSet(state, Flags.INSERT)).isFalse(); + assertThat(Flags.isSet(state, Flags.NORMAL)).isTrue(); } @Test public void isPublishOrMerge() { - assertThat(Flags.isPublishOrMerge(0)).isFalse(); - assertThat(Flags.isPublishOrMerge(Flags.INSERT)).isFalse(); + assertThat(Flags.isPublishMergeOrNormal(0)).isFalse(); + assertThat(Flags.isPublishMergeOrNormal(Flags.INSERT)).isFalse(); + assertThat(Flags.isPublishMergeOrNormal(Flags.RECURSE)).isFalse(); - assertThat(Flags.isPublishOrMerge(Flags.PUBLISH)).isTrue(); - assertThat(Flags.isPublishOrMerge(Flags.MERGE)).isTrue(); + assertThat(Flags.isPublishMergeOrNormal(Flags.PUBLISH)).isTrue(); + assertThat(Flags.isPublishMergeOrNormal(Flags.MERGE)).isTrue(); + assertThat(Flags.isPublishMergeOrNormal(Flags.NORMAL)).isTrue(); int mergePublish = Flags.setMerge(Flags.setPublish(0)); - assertThat(Flags.isPublishOrMerge(mergePublish)).isTrue(); + assertThat(Flags.isPublishMergeOrNormal(mergePublish)).isTrue(); } } diff --git a/src/test/java/org/tests/model/onetoone/TestOneToOneOrphanStringId.java b/src/test/java/org/tests/model/onetoone/TestOneToOneOrphanStringId.java index de738af4e..1a16f50d6 100644 --- a/src/test/java/org/tests/model/onetoone/TestOneToOneOrphanStringId.java +++ b/src/test/java/org/tests/model/onetoone/TestOneToOneOrphanStringId.java @@ -12,10 +12,37 @@ import static org.assertj.core.api.Assertions.assertThat; public class TestOneToOneOrphanStringId extends BaseTestCase { @Test - public void test() { + public void test_updateInsert() { + + OtoAtwo b = new OtoAtwo("b1", "b test"); + Ebean.save(b); + + OtoAone a = new OtoAone("a1", "a test"); + b.setAone(a); + + LoggedSqlCollector.start(); + + Ebean.save(b); + + List update = LoggedSqlCollector.current(); + assertThat(update).hasSize(2); + assertThat(update.get(0)).contains("insert into oto_aone"); + assertThat(update.get(1)).contains("update oto_atwo set aone_id=? where id=?"); + + Ebean.delete(b); + + List deletes = LoggedSqlCollector.stop(); + assertThat(deletes).hasSize(2); + assertThat(deletes.get(0)).contains("delete from oto_atwo"); + assertThat(deletes.get(1)).contains("delete from oto_aone"); + } + + @Test + public void test_cascade() { + + OtoAone a = new OtoAone("a2", "a test"); + OtoAtwo b = new OtoAtwo("b2", "b test"); - OtoAone a = new OtoAone("a", "a test"); - OtoAtwo b = new OtoAtwo("b", "b test"); b.setAone(a); LoggedSqlCollector.start();