From 4aa64410ad95dc18d774e58e8dc6eb3ce30a1532 Mon Sep 17 00:00:00 2001 From: "Kevin W. Sutter" Date: Mon, 8 Sep 2008 21:34:26 +0000 Subject: [PATCH] OPENJPA-715. Committing the testcase provided by Ekin Sokmen and the patch provided by Fay Wang. Committing the change for both the 1.2.x service stream and 1.3.0 snapshot (trunk). git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@693287 13f79535-47bb-0310-9956-ffa450edef68 --- .../persistence/relations/ChainEntityA.java | 79 ++++++++++++ .../persistence/relations/ChainEntityB.java | 78 ++++++++++++ .../persistence/relations/ChainEntityC.java | 69 +++++++++++ .../relations/TestChainEntities.java | 117 ++++++++++++++++++ 4 files changed, 343 insertions(+) create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityA.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityB.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityC.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestChainEntities.java diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityA.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityA.java new file mode 100644 index 000000000..17b318d58 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityA.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.relations; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToMany; +import javax.persistence.Version; + +@Entity +public class ChainEntityA { + + @Id + @GeneratedValue + private long aId; + + @Version + private Integer optLock; + + @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + protected Set chainEntityBSet; + + public ChainEntityA () { + super (); + } + + public void addChildEntityB (ChainEntityB bean) { + if (null == chainEntityBSet) + chainEntityBSet = new LinkedHashSet (); + chainEntityBSet.add (bean); + } + + public Collection getChildren () { + if (null == chainEntityBSet) + chainEntityBSet = new LinkedHashSet (); + return chainEntityBSet; + } + + private String name; + + public String getName () { + return name; + } + + public void setName (String name) { + this.name = name; + } + + public long getId () { + return aId; + } + + public void setId (long id) { + this.aId = id; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityB.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityB.java new file mode 100644 index 000000000..5722823e6 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityB.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.relations; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Version; + +@Entity +public class ChainEntityB { + + @Id + @GeneratedValue + private long bId; + + @Version + private Integer optLock; + + //cascade = CascadeType.ALL, + @OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "chainEntityB") + protected Set chainEntityCSet = null; + + public void addChainEntityC (ChainEntityC bean) { + if (null == chainEntityCSet) + chainEntityCSet = new LinkedHashSet (); + chainEntityCSet.add (bean); + bean.setChainEntityB (this); + } + + public Collection getChainEntityCSet () { + if (null == chainEntityCSet) + chainEntityCSet = new LinkedHashSet (); + return chainEntityCSet; + } + + private String name; + + public String getName () { + return name; + } + + public void setName (String name) { + this.name = name; + } + + public long getId () { + return bId; + } + + public void setId (long id) { + this.bId = id; + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityC.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityC.java new file mode 100644 index 000000000..334ed5c76 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/ChainEntityC.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.relations; + +import javax.persistence.Basic; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.Version; + +@Entity +public class ChainEntityC { + + @Id + @GeneratedValue + private long cId; + + @Version + private Integer optLock; + + @ManyToOne(fetch = FetchType.EAGER, cascade=CascadeType.ALL) + protected ChainEntityB chainEntityB; + + @Basic + protected long chainEntityBId; + + public void setChainEntityB (ChainEntityB b) { + this.chainEntityB = b; +// this.chainEntityBId = null == b ? 0 : b.getId (); + } + + private String name; + + public String getName () { + return name; + } + + public void setName (String name) { + this.name = name; + } + + public long getId () { + return cId; + } + + public void setId (long id) { + this.cId = id; + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestChainEntities.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestChainEntities.java new file mode 100644 index 000000000..c0c457d4d --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestChainEntities.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.relations; + +import javax.persistence.EntityManager; + +import org.apache.openjpa.persistence.test.SingleEMFTestCase; + +public class TestChainEntities extends SingleEMFTestCase { + + /* + * Set this magical number to 3 or less to avoid the error. + */ + private static final int MAGICAL_NUMBER = 50; + + long aid; + + public void setUp () { + setUp (ChainEntityA.class, ChainEntityB.class, ChainEntityC.class); + // Create A + ChainEntityA a = new ChainEntityA (); + a.setName ("TEST_A"); + // Persist A + EntityManager em = emf.createEntityManager (); + em.getTransaction ().begin (); + em.persist (a); + aid = a.getId (); + em.getTransaction ().commit (); + em.close (); + System.out.println ("ChainEntityA id = " + aid); + } + + public void testChainEntities () { + chainUpdate (); + } + + protected void chainUpdate () { + // Get A + ChainEntityA a = getA (); + // Create B + ChainEntityB b = new ChainEntityB (); + b.setName ("Test_B_"); + ChainEntityC c; + /* + * Create and add C to B. Increasing the number of iterations (number of + * ChainEntityC) increases the probability to get the unique key + * constraint violation error. + */ + for (int i = 1; i <= MAGICAL_NUMBER; i++) { + c = new ChainEntityC (); + c.setName ("Test_C_" + i); + b.addChainEntityC (c); + } + a.addChildEntityB (b); + // dump (a); // debug + // Merge A + EntityManager em = emf.createEntityManager (); + em.getTransaction ().begin (); + a = em.merge (a); + /* + * workaround: Uncommenting following line is a workaround. If we + * retrive Ids of ChainEntityC objects after merge but before commit we + * don't get the error. + */ + //dump (a); + em.getTransaction ().commit (); + em.close (); + // dump (getA ()); // debug + } + + /** + * Get created ChainEntityA using aid field. + * + * @return + */ + protected ChainEntityA getA () { + EntityManager em = emf.createEntityManager (); + ChainEntityA a = em.find (ChainEntityA.class, aid); + em.close (); + return a; + } + + /** + * Print the object graph of given ChainEntityA to System.out + * + * @param testA + */ + protected void dump (ChainEntityA testA) { + System.out.println ("-------"); + System.out.println (testA.getName () + "[" + testA.getId () + "]"); + for (ChainEntityB testB : testA.getChildren ()) { + System.out.println (testB.getName () + "[" + testB.getId () + "]"); + for (ChainEntityC testC : testB.getChainEntityCSet ()) { + System.out.println (testC.getName () + "[" + testC.getId () + + "]"); + } + } + System.out.println ("-------"); + } + +}