diff --git a/jpa/ordercolumn/pom.xml b/jpa/ordercolumn/pom.xml new file mode 100644 index 000000000..1192dd790 --- /dev/null +++ b/jpa/ordercolumn/pom.xml @@ -0,0 +1,14 @@ + + 4.0.0 + + org.javaee7.jpa + jpa-samples + 1.0-SNAPSHOT + ../pom.xml + + + ordercolumn + war + + diff --git a/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionaljoin/Child.java b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionaljoin/Child.java new file mode 100644 index 000000000..9dd2113f8 --- /dev/null +++ b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionaljoin/Child.java @@ -0,0 +1,38 @@ +package org.javaee7.jpa.ordercolumn.entity.bidirectionaljoin; + +import static javax.persistence.GenerationType.IDENTITY; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +@Entity +public class Child { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name = "parent_id", insertable = false, updatable = false) + private Parent parent; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + +} diff --git a/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionaljoin/Parent.java b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionaljoin/Parent.java new file mode 100644 index 000000000..ce6c67bd2 --- /dev/null +++ b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionaljoin/Parent.java @@ -0,0 +1,45 @@ +package org.javaee7.jpa.ordercolumn.entity.bidirectionaljoin; + +import static javax.persistence.CascadeType.ALL; +import static javax.persistence.FetchType.EAGER; +import static javax.persistence.GenerationType.IDENTITY; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; + +@Entity +public class Parent { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + @OneToMany(cascade = ALL, fetch = EAGER) + @OrderColumn + @JoinColumn(name = "parent_id") + private List children = new ArrayList<>(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + +} diff --git a/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionalmappedby/Child.java b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionalmappedby/Child.java new file mode 100644 index 000000000..555367b4d --- /dev/null +++ b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionalmappedby/Child.java @@ -0,0 +1,36 @@ +package org.javaee7.jpa.ordercolumn.entity.bidirectionalmappedby; + +import static javax.persistence.GenerationType.IDENTITY; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +public class Child { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + @ManyToOne + private Parent parent; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + +} diff --git a/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionalmappedby/Parent.java b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionalmappedby/Parent.java new file mode 100644 index 000000000..197150f82 --- /dev/null +++ b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/bidirectionalmappedby/Parent.java @@ -0,0 +1,43 @@ +package org.javaee7.jpa.ordercolumn.entity.bidirectionalmappedby; + +import static javax.persistence.CascadeType.ALL; +import static javax.persistence.FetchType.EAGER; +import static javax.persistence.GenerationType.IDENTITY; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; + +@Entity +public class Parent { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + @OneToMany(cascade = ALL, fetch = EAGER, mappedBy = "parent") + @OrderColumn + private List children = new ArrayList<>(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + +} diff --git a/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/unidirectional/Child.java b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/unidirectional/Child.java new file mode 100644 index 000000000..8a5d2a895 --- /dev/null +++ b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/unidirectional/Child.java @@ -0,0 +1,24 @@ +package org.javaee7.jpa.ordercolumn.entity.unidirectional; + +import static javax.persistence.GenerationType.IDENTITY; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Child { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + +} diff --git a/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/unidirectional/Parent.java b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/unidirectional/Parent.java new file mode 100644 index 000000000..25cd1dc89 --- /dev/null +++ b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/entity/unidirectional/Parent.java @@ -0,0 +1,45 @@ +package org.javaee7.jpa.ordercolumn.entity.unidirectional; + +import static javax.persistence.CascadeType.ALL; +import static javax.persistence.FetchType.EAGER; +import static javax.persistence.GenerationType.IDENTITY; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; + +@Entity +public class Parent { + + @Id + @GeneratedValue(strategy = IDENTITY) + private Long id; + + @OneToMany(cascade = ALL, fetch = EAGER) + @OrderColumn + @JoinColumn + private List children = new ArrayList<>(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + +} diff --git a/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/service/bidirectionaljoin/OrderColumnTesterService.java b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/service/bidirectionaljoin/OrderColumnTesterService.java new file mode 100644 index 000000000..b9369305b --- /dev/null +++ b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/service/bidirectionaljoin/OrderColumnTesterService.java @@ -0,0 +1,23 @@ +package org.javaee7.jpa.ordercolumn.service.bidirectionaljoin; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.javaee7.jpa.ordercolumn.entity.bidirectionaljoin.Parent; + +@Stateless +public class OrderColumnTesterService { + + @PersistenceContext + EntityManager entityManager; + + public Parent save(Parent parent) { + return entityManager.merge(parent); + } + + public Parent getParentById(Long id) { + return entityManager.find(Parent.class, id); + } + +} diff --git a/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/service/bidirectionalmappedby/OrderColumnTesterService.java b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/service/bidirectionalmappedby/OrderColumnTesterService.java new file mode 100644 index 000000000..eba4bff9e --- /dev/null +++ b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/service/bidirectionalmappedby/OrderColumnTesterService.java @@ -0,0 +1,23 @@ +package org.javaee7.jpa.ordercolumn.service.bidirectionalmappedby; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.javaee7.jpa.ordercolumn.entity.bidirectionalmappedby.Parent; + +@Stateless +public class OrderColumnTesterService { + + @PersistenceContext + EntityManager entityManager; + + public Parent save(Parent parent) { + return entityManager.merge(parent); + } + + public Parent getParentById(Long id) { + return entityManager.find(Parent.class, id); + } + +} diff --git a/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/service/unidirectional/OrderColumnTesterService.java b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/service/unidirectional/OrderColumnTesterService.java new file mode 100644 index 000000000..f6e1d9ed4 --- /dev/null +++ b/jpa/ordercolumn/src/main/java/org/javaee7/jpa/ordercolumn/service/unidirectional/OrderColumnTesterService.java @@ -0,0 +1,23 @@ +package org.javaee7.jpa.ordercolumn.service.unidirectional; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.javaee7.jpa.ordercolumn.entity.unidirectional.Parent; + +@Stateless +public class OrderColumnTesterService { + + @PersistenceContext + EntityManager entityManager; + + public Parent save(Parent parent) { + return entityManager.merge(parent); + } + + public Parent getParentById(Long id) { + return entityManager.find(Parent.class, id); + } + +} diff --git a/jpa/ordercolumn/src/main/resources/META-INF/persistence.xml b/jpa/ordercolumn/src/main/resources/META-INF/persistence.xml new file mode 100644 index 000000000..884c25b24 --- /dev/null +++ b/jpa/ordercolumn/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/jpa/ordercolumn/src/test/java/org/javaee7/jpa/ordercolumn/OrderColumnBiJoinTest.java b/jpa/ordercolumn/src/test/java/org/javaee7/jpa/ordercolumn/OrderColumnBiJoinTest.java new file mode 100644 index 000000000..516e0b3f9 --- /dev/null +++ b/jpa/ordercolumn/src/test/java/org/javaee7/jpa/ordercolumn/OrderColumnBiJoinTest.java @@ -0,0 +1,194 @@ +package org.javaee7.jpa.ordercolumn; + +import static org.junit.Assert.assertEquals; + +import javax.ejb.EJB; +import javax.persistence.JoinColumn; +import javax.persistence.OrderColumn; + +import org.javaee7.jpa.ordercolumn.entity.bidirectionaljoin.Child; +import org.javaee7.jpa.ordercolumn.entity.bidirectionaljoin.Parent; +import org.javaee7.jpa.ordercolumn.service.bidirectionaljoin.OrderColumnTesterService; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * This tests and demonstrates the {@link OrderColumn} annotation when used together with a + * bi-directional parent-child mapping, where the child holds a foreign key to the parent. + * + *

+ * This is a variation on the normal oneToMany mapping using two {@link JoinColumn} annotations + * instead of using the mappedBy attribute. + * + *

+ * In this mapping the position each child has in the parent's list is stored in the + * child table and fully managed by JPA. This means that this position index does + * not explicitly show up in the object model. + * + *

+ * Example SQL DDL (h2 syntax) + *

+ *      create table Parent (
+ *          id bigint generated by default as identity,
+ *          
+ *          primary key (id)
+ *      );
+ *      
+ *      create table Child (
+ *           id bigint generated by default as identity,
+ *           parent_id bigint,
+ *           children_ORDER integer,
+ *           
+ *           primary key (id),
+ *           foreign key (parent_id) references Parent
+ *       );
+ * 
+ * + * + * @author Arjan Tijms + */ +@RunWith(Arquillian.class) +public class OrderColumnBiJoinTest { + + @Deployment + private static Archive createDeployment() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, Child.class.getPackage()) + .addPackages(true, OrderColumnTesterService.class.getPackage()) + .addAsResource("META-INF/persistence.xml"); + } + + @EJB + private OrderColumnTesterService indexColumnTesterService; + + @Test + public void saveInOneGo() { + Parent parent = new Parent(); + + Child child1 = new Child(); + child1.setParent(parent); + + Child child2 = new Child(); + child2.setParent(parent); + + parent.getChildren().add(child1); + parent.getChildren().add(child2); + + parent = indexColumnTesterService.save(parent); + + // Reload parent fresh from data source again + Parent savedParent = indexColumnTesterService.getParentById(parent.getId()); + + assertEquals("2 children added to parent and saved, but after re-loading number of chilren different", + 2, savedParent.getChildren().size() + ); + } + + /** + * Saves a parent instance first, then adds two children instances and saves again. + * + *

+ * Example sequence of insert/update statements that may be generated to accomplish this: + *

+     * insert into Parent (id) values (null)
+     * insert into Child (id) values (null)
+     * insert into Child (id) values (null)
+     * 
+     * update Child set parent_id = 1, children_ORDER = 0 where id = 1 
+     * update Child set parent_id = 1, children_ORDER = 1 where id = 2 
+     * 
+ * + */ + @Test + public void saveParentSeparatelyFirst() { + + Parent parent = indexColumnTesterService.save(new Parent()); + + Child child1 = new Child(); + child1.setParent(parent); + + Child child2 = new Child(); + child2.setParent(parent); + + parent.getChildren().add(child1); + parent.getChildren().add(child2); + + parent = indexColumnTesterService.save(parent); + + Parent savedParent = indexColumnTesterService.getParentById(parent.getId()); + + assertEquals("2 children added to parent and saved, but after re-loading number of chilren different", + 2, savedParent.getChildren().size() + ); + + } + + @Test + public void saveParentWithOneChildFirst() { + + Parent parent = new Parent(); + Child child1 = new Child(); + child1.setParent(parent); + parent.getChildren().add(child1); + + // Save parent with 1 child in one go + parent = indexColumnTesterService.save(parent); + + Child child2 = new Child(); + child2.setParent(parent); + parent.getChildren().add(child2); + + // Save parent again with second child + parent = indexColumnTesterService.save(parent); + + Parent savedParent = indexColumnTesterService.getParentById(parent.getId()); + + assertEquals("2 children added to parent and saved, but after re-loading number of chilren different", + 2, savedParent.getChildren().size() + ); + } + + @Test + public void saveParentWithChildrenThenDeleteOned() { + + Parent parent = new Parent(); + + Child child1 = new Child(); + child1.setParent(parent); + parent.getChildren().add(child1); + + Child child2 = new Child(); + child2.setParent(parent); + parent.getChildren().add(child2); + + Child child3 = new Child(); + child3.setParent(parent); + parent.getChildren().add(child3); + + // Save parent with 3 children + parent = indexColumnTesterService.save(parent); + + Parent savedParent = indexColumnTesterService.getParentById(parent.getId()); + + assertEquals("3 children added to parent and saved, but after re-loading number of chilren different", + 3, savedParent.getChildren().size() + ); + + // Removing child at position 1 and saving again + savedParent.getChildren().remove(1); + + savedParent = indexColumnTesterService.save(savedParent); + savedParent = indexColumnTesterService.getParentById(savedParent.getId()); + + assertEquals("2 children added to parent and saved, but after re-loading number of chilren different", + 2, savedParent.getChildren().size() + ); + + } + +} diff --git a/jpa/ordercolumn/src/test/java/org/javaee7/jpa/ordercolumn/OrderColumnBiMappedByTest.java b/jpa/ordercolumn/src/test/java/org/javaee7/jpa/ordercolumn/OrderColumnBiMappedByTest.java new file mode 100644 index 000000000..a149b04a6 --- /dev/null +++ b/jpa/ordercolumn/src/test/java/org/javaee7/jpa/ordercolumn/OrderColumnBiMappedByTest.java @@ -0,0 +1,132 @@ +package org.javaee7.jpa.ordercolumn; + +import static org.junit.Assert.assertEquals; + +import javax.ejb.EJB; +import javax.persistence.OrderColumn; + +import org.javaee7.jpa.ordercolumn.entity.bidirectionalmappedby.Child; +import org.javaee7.jpa.ordercolumn.entity.bidirectionalmappedby.Parent; +import org.javaee7.jpa.ordercolumn.service.bidirectionalmappedby.OrderColumnTesterService; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * This tests and demonstrates the {@link OrderColumn} annotation when used together with a + * bi-directional parent-child mapping, where the child holds a foreign key to the parent. + * + *

+ * This is the normal oneToMany mapping using the mappedBy attribute. + * Even though this is the most straightforward mapping, because of a mis-interpretation + * in the JPA spec it was believed for years that this mapping did not have to be + * supported (see https://hibernate.atlassian.net/browse/HHH-5732 among others) + * + *

+ * In this mapping the position each child has in the parent's list is stored in the + * child table and fully managed by JPA. This means that this position index does + * not explicitly show up in the object model. + * + *

+ * Example SQL DDL (h2 syntax) + *

+ *      create table Parent (
+ *          id bigint generated by default as identity,
+ *          
+ *          primary key (id)
+ *      );
+ *      
+ *      create table Child (
+ *           id bigint generated by default as identity,
+ *           parent_id bigint,
+ *           children_ORDER integer,
+ *           
+ *           primary key (id),
+ *           foreign key (parent_id) references Parent
+ *       );
+ * 
+ * + * + * @author Arjan Tijms + */ +@RunWith(Arquillian.class) +public class OrderColumnBiMappedByTest { + + @Deployment + private static Archive createDeployment() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, Parent.class.getPackage()) + .addPackages(true, OrderColumnTesterService.class.getPackage()) + .addAsResource("META-INF/persistence.xml"); + } + + @EJB + private OrderColumnTesterService indexColumnTesterService; + + @Test + public void saveInOneGo() { + + Parent parent = new Parent(); + + Child child1 = new Child(); + child1.setParent(parent); + + Child child2 = new Child(); + child2.setParent(parent); + + parent.getChildren().add(child1); + parent.getChildren().add(child2); + + parent = indexColumnTesterService.save(parent); + + Parent savedParent = indexColumnTesterService.getParentById(parent.getId()); + + assertEquals("2 children added to parent and saved, but after re-loading number of chilren different", + 2, savedParent.getChildren().size() + ); + } + + /** + * Saves a parent instance first, then adds two children instances and saves again. + * + *

+ * Example sequence of insert/update statements that may be generated to accomplish this: + *

+     * insert into Parent (id) values (null)
+     * insert into Child (id, parent_id) values (null, 1) 
+     * insert into Child (id, parent_id) values (null, 1)
+     *
+     * update Child set children_ORDER = 0 where id = 1
+     * update Child set children_ORDER = 1 where id = 2
+     * 
+ * + */ + @Test + public void saveParentSeparatelyFirst() { + + Parent parent = indexColumnTesterService.save(new Parent()); + + Child child1 = new Child(); + child1.setParent(parent); + + Child child2 = new Child(); + child2.setParent(parent); + + parent.getChildren().add(child1); + parent.getChildren().add(child2); + + parent = indexColumnTesterService.save(parent); + + Parent savedParent = indexColumnTesterService.getParentById(parent.getId()); + + assertEquals("2 children added to parent and saved, but after re-loading number of chilren different", + 2, savedParent.getChildren().size() + ); + + } + +} \ No newline at end of file diff --git a/jpa/ordercolumn/src/test/java/org/javaee7/jpa/ordercolumn/OrderColumnUniTest.java b/jpa/ordercolumn/src/test/java/org/javaee7/jpa/ordercolumn/OrderColumnUniTest.java new file mode 100644 index 000000000..67079628d --- /dev/null +++ b/jpa/ordercolumn/src/test/java/org/javaee7/jpa/ordercolumn/OrderColumnUniTest.java @@ -0,0 +1,172 @@ +package org.javaee7.jpa.ordercolumn; + +import static org.junit.Assert.assertEquals; + +import javax.ejb.EJB; +import javax.persistence.OrderColumn; + +import org.javaee7.jpa.ordercolumn.entity.unidirectional.Child; +import org.javaee7.jpa.ordercolumn.entity.unidirectional.Parent; +import org.javaee7.jpa.ordercolumn.service.unidirectional.OrderColumnTesterService; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * This tests and demonstrates the {@link OrderColumn} annotation when used together with a + * uni-directional parent-child mapping, where the child table holds a foreign key to the parent. + * + *

+ * In this mapping the position each child has in the parent's list is stored in the + * child table and fully managed by JPA. This means that this position index does + * not explicitly show up in the object model. + * + *

+ * Example SQL DDL (h2 syntax) + *

+ *      create table Parent (
+ *          id bigint generated by default as identity,
+ *          
+ *          primary key (id)
+ *      );
+ *      
+ *      create table Child (
+ *           id bigint generated by default as identity,
+ *           children_id bigint,
+ *           children_ORDER integer,
+ *           
+ *           primary key (id),
+ *           foreign key (children_id) references Parent
+ *       );
+ * 
+ * + * + * @author Arjan Tijms + */ +@RunWith(Arquillian.class) +public class OrderColumnUniTest { + + @Deployment + private static Archive createDeployment() { + return ShrinkWrap.create(WebArchive.class) + .addPackages(true, Child.class.getPackage()) + .addPackages(true, OrderColumnTesterService.class.getPackage()) + .addAsResource("META-INF/persistence.xml"); + } + + @EJB + private OrderColumnTesterService indexColumnTesterService; + + /** + * Saves a parent instance with 2 children in its children collection in one operation. + * + *

+ * Example sequence of insert/update statements that may be generated to accomplish this: + *

+     * insert into Parent (id) values (null)
+     * insert into Child (id) values (null)
+     * insert into Child (id) values (null)
+     *
+     * update Child set children_id = 1, children_ORDER = 0 where id = 1 
+     * update Child set children_id = 1, children_ORDER = 1 where id = 2
+     * 
+ * + */ + @Test + public void saveInOneGo() { + + Parent parent = new Parent(); + Child child1 = new Child(); + Child child2 = new Child(); + + parent.getChildren().add(child1); + parent.getChildren().add(child2); + + parent = indexColumnTesterService.save(parent); + + Parent savedParent = indexColumnTesterService.getParentById(parent.getId()); + + assertEquals("2 children added to parent and saved, but after re-loading number of chilren different", + 2, savedParent.getChildren().size() + ); + } + + /** + * Saves a parent instance first, then adds two children instances and saves again. + * + *

+ * Example sequence of insert/update statements that may be generated to accomplish this: + *

+     * insert into Parent (id) values (null)
+     * insert into Child (id) values (null)
+     * insert into Child (id) values (null)
+     *
+     * update Child set children_id = 1, children_ORDER = 0 where id = 1 
+     * update Child set children_id = 1, children_ORDER = 1 where id = 2
+     * 
+ * + */ + @Test + public void saveParentSeparatelyFirst() { + + Parent parent = indexColumnTesterService.save(new Parent()); + + Child child1 = new Child(); + Child child2 = new Child(); + + parent.getChildren().add(child1); + parent.getChildren().add(child2); + + parent = indexColumnTesterService.save(parent); + + Parent savedParent = indexColumnTesterService.getParentById(parent.getId()); + + assertEquals("2 children added to parent and saved, but after re-loading number of chilren different", + 2, savedParent.getChildren().size() + ); + + } + + /** + * Saves a parent with one child in its children collection first, then adds another child and saves again. + * + *

+ * Example sequence of insert/update statements that may be generated to accomplish this: + *

+     * insert into Parent (id) values (null)
+     * insert into Child (id) values (null)
+     * update Child set children_id = 1, children_ORDER = 0 where id = 1
+     * 
+     * insert into Child (id) values (null)
+     * update Child set children_id = 1, children_ORDER = 1 where id = 2
+     * 
+ */ + @Test + public void saveParentWithOneChildFirst() { + + Parent parent = new Parent(); + Child child1 = new Child(); + parent.getChildren().add(child1); + + // Save parent with 1 child in one go + parent = indexColumnTesterService.save(parent); + + Child child2 = new Child(); + parent.getChildren().add(child2); + + // Save parent again with second child + parent = indexColumnTesterService.save(parent); + + Parent savedParent = indexColumnTesterService.getParentById(parent.getId()); + + assertEquals("2 children added to parent and saved, but after re-loading number of chilren different", + 2, savedParent.getChildren().size() + ); + + } + +} diff --git a/jpa/pom.xml b/jpa/pom.xml index b5f48b112..2b49e6416 100644 --- a/jpa/pom.xml +++ b/jpa/pom.xml @@ -29,6 +29,7 @@ jndi-context locking-optimistic locking-pessimistic + ordercolumn pu-typesafe schema-gen-metadata schema-gen-scripts