diff --git a/src/main/java/io/ebeaninternal/server/persist/SaveManyBeans.java b/src/main/java/io/ebeaninternal/server/persist/SaveManyBeans.java index 653d387f1..cb4a87cb6 100644 --- a/src/main/java/io/ebeaninternal/server/persist/SaveManyBeans.java +++ b/src/main/java/io/ebeaninternal/server/persist/SaveManyBeans.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import static io.ebeaninternal.server.persist.DmlUtil.isNullOrZero; @@ -108,7 +109,7 @@ public class SaveManyBeans extends SaveManyBase { BeanProperty orderColumn = null; boolean hasOrderColumn = many.hasOrderColumn(); if (hasOrderColumn) { - if (!insertedParent && canSkipForOrderColumn()) { + if (!insertedParent && canSkipForOrderColumn() && saveRecurseSkippable) { return; } orderColumn = targetDescriptor.getOrderColumn(); @@ -157,7 +158,7 @@ public class SaveManyBeans extends SaveManyBase { if (many.hasJoinTable()) { skipSavingThisBean = targetDescriptor.isReference(ebi); } else { - if (orderColumn != null) { + if (orderColumn != null && !Objects.equals(sortOrder, orderColumn.getValue(detail))) { orderColumn.setValue(detail, sortOrder); ebi.setDirty(true); } diff --git a/src/test/java/org/tests/cascade/TestOrderedList.java b/src/test/java/org/tests/cascade/TestOrderedList.java index 75d2b56f8..5ccc781f9 100644 --- a/src/test/java/org/tests/cascade/TestOrderedList.java +++ b/src/test/java/org/tests/cascade/TestOrderedList.java @@ -85,11 +85,10 @@ public class TestOrderedList extends BaseTestCase { Ebean.save(fresh); sql = LoggedSqlCollector.current(); - assertThat(sql).hasSize(8); - assertSql(sql.get(0)).contains("update om_ordered_master set name=?, version=?"); - assertSql(sql.get(1)).contains("update om_ordered_detail set version=?, sort_order=? where id=? and version=?"); - assertThat(sql.get(3)).contains("update om_ordered_detail set name=?, version=?, sort_order=? where id=? and version=?"); - + assertThat(sql).hasSize(3); + assertSql(sql.get(0)).contains("update om_ordered_master set name=?, version=? where id=? and version=?; -- bind(m1-mod3"); + assertSql(sql.get(1)).contains("update om_ordered_detail set name=?, version=?, sort_order=? where id=? and version=?"); + assertThat(sql.get(2)).contains("bind(was 1,3,2,"); Ebean.delete(fresh); diff --git a/src/test/java/org/tests/order/OrderReferencedChild.java b/src/test/java/org/tests/order/OrderReferencedChild.java index 22215a3e9..47a2f6ed5 100644 --- a/src/test/java/org/tests/order/OrderReferencedChild.java +++ b/src/test/java/org/tests/order/OrderReferencedChild.java @@ -1,8 +1,12 @@ package org.tests.order; +import javax.persistence.CascadeType; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; +import java.util.List; @Entity @DiscriminatorValue("D") @@ -13,6 +17,10 @@ public class OrderReferencedChild extends OrderReferencedParent { @ManyToOne OrderMaster master; + @OneToMany(cascade = CascadeType.ALL, mappedBy = "child", orphanRemoval = true) + @OrderColumn(name = "sort_order") + List toys; + public OrderReferencedChild(final String name) { super(name); } @@ -32,4 +40,12 @@ public class OrderReferencedChild extends OrderReferencedParent { public void setMaster(final OrderMaster master) { this.master = master; } + + public List getToys() { + return toys; + } + + public void setToys(final List toys) { + this.toys = toys; + } } diff --git a/src/test/java/org/tests/order/OrderToy.java b/src/test/java/org/tests/order/OrderToy.java new file mode 100644 index 000000000..a305b47c9 --- /dev/null +++ b/src/test/java/org/tests/order/OrderToy.java @@ -0,0 +1,45 @@ +package org.tests.order; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class OrderToy { + + @Id + Integer id; + + String title; + + @ManyToOne + OrderReferencedChild child; + + public OrderToy(final String title) { + this.title = title; + } + + public Integer getId() { + return id; + } + + public void setId(final Integer id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(final String title) { + this.title = title; + } + + public OrderReferencedChild getChild() { + return child; + } + + public void setChild(final OrderReferencedChild child) { + this.child = child; + } +} diff --git a/src/test/java/org/tests/order/TestOrderColumn.java b/src/test/java/org/tests/order/TestOrderColumn.java index cb0477e31..3cd40ea4d 100644 --- a/src/test/java/org/tests/order/TestOrderColumn.java +++ b/src/test/java/org/tests/order/TestOrderColumn.java @@ -2,8 +2,11 @@ package org.tests.order; import io.ebean.Ebean; import io.ebean.TransactionalTestCase; +import org.ebeantest.LoggedSqlCollector; import org.junit.Test; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThat; public class TestOrderColumn extends TransactionalTestCase { @@ -28,4 +31,50 @@ public class TestOrderColumn extends TransactionalTestCase { assertThat(result.getChildren()).extracting(OrderReferencedChild::getChildName).containsExactly("c0", "c1", "c2", "c3", "c4"); } + @Test + public void testModifyTree() { + final OrderMaster master = new OrderMaster(); + + for (int i = 0; i < 5; i++) { + final OrderReferencedChild child = new OrderReferencedChild("p" + i); + child.setChildName("c" + i); + + for (int j = 0; j < 3; j++) { + final OrderToy toy = new OrderToy("t" + i + j); + child.getToys().add(toy); + } + + master.getChildren().add(child); + } + + Ebean.save(master); + + final OrderMaster result = Ebean.find(OrderMaster.class).findOne(); + + final List children = result.getChildren(); + assertThat(children).hasSize(5); + + for (int i = 0; i < 5; i++) { + final List toys = children.get(i).getToys(); + + for (int j = 0; j < 3; j++) { + final OrderToy toy = toys.get(j); + assertThat(toy.getTitle()).isEqualTo("t" + i + j); + } + } + + // modify two toys + children.get(1).getToys().get(0).setTitle("tt10"); + children.get(3).getToys().get(2).setTitle("tt32"); + + LoggedSqlCollector.start(); + Ebean.save(result); + final List sql = LoggedSqlCollector.current(); + assertThat(sql).hasSize(3); + + assertThat(sql.get(0)).contains("update order_toy set title=?, sort_order=? where id=?"); + assertThat(sql.get(1)).contains("bind(tt10"); + assertThat(sql.get(2)).contains("bind(tt32"); + } + }