mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-23 14:32:04 +00:00
#1472 - Cascade insert with managed id ... results in update rather than insert statement
This commit is contained in:
@@ -1307,14 +1307,22 @@ public final class PersistRequestBean<T> 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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<T> 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
|
||||
|
||||
@@ -5,7 +5,7 @@ package io.ebeaninternal.server.persist;
|
||||
* <p>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String> 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<String> 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();
|
||||
|
||||
Reference in New Issue
Block a user