You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by ht...@apache.org on 2011/06/29 17:18:13 UTC

svn commit: r1141131 - in /openjpa/branches/1.2.x: openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/

Author: hthomann
Date: Wed Jun 29 15:18:08 2011
New Revision: 1141131

URL: http://svn.apache.org/viewvc?rev=1141131&view=rev
Log:
OPENJPA-2006: If flushing, also pre-flush non-provisional entities to allow sequence ID population - applied Jeremy's 1.2.x patch.

Added:
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Assignment.java   (with props)
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/ClassPeriod.java   (with props)
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Course.java   (with props)
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/SubTopic.java   (with props)
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/TestCascadingFlush.java   (with props)
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Topic.java   (with props)
Modified:
    openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
    openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java

Modified: openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java?rev=1141131&r1=1141130&r2=1141131&view=diff
==============================================================================
--- openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java (original)
+++ openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java Wed Jun 29 15:18:08 2011
@@ -1963,8 +1963,10 @@ public class BrokerImpl
         try {
             if (flush) {
                 // call pre store on all currently transactional objs
-                for (Iterator itr = transactional.iterator(); itr.hasNext();)
-                    ((StateManagerImpl) itr.next()).beforeFlush(reason, _call);
+                for (Iterator itr = transactional.iterator(); itr.hasNext();) {
+                	StateManagerImpl sm = (StateManagerImpl) itr.next();
+                    sm.beforeFlush(reason, _call);
+                }
                 flushAdditions(transactional, reason);
             }
 
@@ -4786,4 +4788,8 @@ public class BrokerImpl
             throw new ObjectExistsException(_loc.get("cache-exists",
                 obj.getClass().getName(), id)).setFailedObject(obj);
     }
+    
+    protected boolean isFlushing() {
+    	return ((_flags & FLAG_FLUSHING) != 0);
+    }
 }

Modified: openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java?rev=1141131&r1=1141130&r2=1141131&view=diff
==============================================================================
--- openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java (original)
+++ openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java Wed Jun 29 15:18:08 2011
@@ -762,9 +762,16 @@ class SingleFieldManager
             sm = _broker.getStateManager(obj);
             if (sm == null || !sm.isProvisional()) { 
                 sm = _broker.persist(obj, null, true, call);
+
                 // ensure generated IDs get assigned properly
                 if (!logical)
                     ((StateManagerImpl)sm).assignObjectId(false, true);
+
+                // Call preFetch on this and any related persistent fields.
+                // This will ensure IDs get assigned to those that need them.
+                if (_broker.isFlushing()) {
+                	((StateManagerImpl)sm).preFlush(logical, call);
+                }
             }
         }
 

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Assignment.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Assignment.java?rev=1141131&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Assignment.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Assignment.java Wed Jun 29 15:18:08 2011
@@ -0,0 +1,77 @@
+/*
+ * 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.flush;
+
+import java.io.Serializable;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="FL_ASSIGN")
+public class Assignment implements Serializable {
+
+    private static final long serialVersionUID = -7707299604883998179L;
+    
+    @Id
+    @Column(name="ASSIGN_ID")
+    @SequenceGenerator(name="assignIdSeq", sequenceName="FL_ASSIGN_SEQ")
+    @GeneratedValue(generator="assignIdSeq", strategy=GenerationType.SEQUENCE)
+    protected Long assignId;
+    
+    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, fetch=FetchType.LAZY)
+    @JoinColumn(name="TOPIC_ID")
+    protected Topic topic;
+    
+    @Column(name="ASSIGN_TEXT")
+    protected String assignText;
+
+    public Long getAssignmentId() {
+        return assignId;
+    }
+
+    public void setAssignmentId(Long assignId) {
+        this.assignId = assignId;
+    }
+
+    public Topic getTopic() {
+        return topic;
+    }
+
+    public void setTopic(Topic topic) {
+        this.topic = topic;
+    }
+
+    public String getAssignmentText() {
+        return assignText;
+    }
+
+    public void setAssignmentText(String assignText) {
+        this.assignText = assignText;
+    }
+}

Propchange: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Assignment.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/ClassPeriod.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/ClassPeriod.java?rev=1141131&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/ClassPeriod.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/ClassPeriod.java Wed Jun 29 15:18:08 2011
@@ -0,0 +1,93 @@
+/*
+ * 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.flush;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.ElementDependent;
+
+@Entity
+@Table(name="FL_CLP")
+public class ClassPeriod implements Serializable {
+
+    private static final long serialVersionUID = -5315185851562144594L;
+
+    @Id
+    @Column(name="CLP_ID")
+    @SequenceGenerator(name="clpIdSeq", sequenceName="FL_CLP_SEQ")
+    @GeneratedValue(generator="clpIdSeq", strategy=GenerationType.SEQUENCE)
+    protected Long clpId;
+    
+    @Column(name="CLP_TEXT")
+    protected String clpText;
+    
+    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, fetch=FetchType.LAZY)
+    @JoinColumn(name="COURSE_ID")
+    protected Course course;
+    
+    @OneToMany(mappedBy="clp",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
+    @ElementDependent(true)
+    protected Set<Topic> topics;
+    
+    public Set<Topic> getTopics() {
+        return topics;
+    }
+    
+    public void setTopics(Set<Topic> topics) {
+        this.topics = topics;
+    }
+    
+    public Long getClassPeriodId() {
+        return clpId;
+    }
+    
+    public void setClassPeriodId(Long clpId) {
+        this.clpId = clpId;
+    }
+    
+    public Course getCourse() {
+        return course;
+    }
+    
+    public void setCourse(Course course) {
+        this.course = course;   
+    }
+    
+    public String getClassPeriodText() {
+        return clpText;
+    }
+    
+    public void setClassPeriodText(String clpText) {
+        this.clpText = clpText;
+    }
+}

Propchange: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/ClassPeriod.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Course.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Course.java?rev=1141131&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Course.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Course.java Wed Jun 29 15:18:08 2011
@@ -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.flush;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.ElementDependent;
+
+@Entity
+@Table(name="FL_COURSE")
+public class Course implements Serializable {
+
+    private static final long serialVersionUID = -5351948190722744801L;
+
+    @Id
+    @Column(name="COURSE_ID")
+    @SequenceGenerator(name="courseIdSeq", sequenceName="FL_COURSE_SEQ")
+    @GeneratedValue(generator="courseIdSeq", strategy=GenerationType.SEQUENCE)
+    protected Long courseId;
+    
+    @Column(name="COURSE_TEXT")
+    protected String courseText;
+    
+    @OneToMany(mappedBy="course", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
+    @ElementDependent(true)
+    protected Set<ClassPeriod> classPeriods;
+
+    public Long getCourseId() {
+        return courseId;
+    }
+
+    public void setCourseId(Long courseId) {
+        this.courseId = courseId;
+    }
+
+    public String getCourseText() {
+        return courseText;
+    }
+
+    public void setCourseText(String courseText) {
+        this.courseText = courseText;
+    }
+
+    public Set<ClassPeriod> getClassPeriods() {
+        return classPeriods;
+    }
+
+    public void setClassPeriods(Set<ClassPeriod> classPeriods) {
+        this.classPeriods = classPeriods;
+    }
+}

Propchange: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Course.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/SubTopic.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/SubTopic.java?rev=1141131&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/SubTopic.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/SubTopic.java Wed Jun 29 15:18:08 2011
@@ -0,0 +1,77 @@
+/*
+ * 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.flush;
+
+import java.io.Serializable;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="FL_SUBTOPIC")
+public class SubTopic implements Serializable {
+
+    private static final long serialVersionUID = 1855479005964448251L;
+
+    @Id
+    @Column(name="SUBTOPIC_ID")
+    @SequenceGenerator(name="subtopicIdSeq", sequenceName="FL_SUBTOPIC_SEQ")
+    @GeneratedValue(generator="subtopicIdSeq", strategy=GenerationType.SEQUENCE)
+    protected Long subtopicId;
+    
+    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, fetch=FetchType.LAZY)
+    @JoinColumn(name="TOPIC_ID")
+    protected Topic topic;
+    
+    @Column(name="SUBTOPIC_TEXT")
+    protected String subtopicText;
+    
+    public Long getSubtopicId() {
+        return subtopicId;
+    }
+
+    public void setSubtopicId(Long subtopicId) {
+        this.subtopicId = subtopicId;
+    }
+
+    public Topic getTopic() {
+        return topic;
+    }
+
+    public void setTopic(Topic topic) {
+        this.topic = topic;
+    }
+
+    public String getSubtopicText() {
+        return subtopicText;
+    }
+
+    public void setSubtopicText(String subtopicText) {
+        this.subtopicText = subtopicText;
+    }
+}

Propchange: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/SubTopic.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/TestCascadingFlush.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/TestCascadingFlush.java?rev=1141131&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/TestCascadingFlush.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/TestCascadingFlush.java Wed Jun 29 15:18:08 2011
@@ -0,0 +1,307 @@
+/*
+ * 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.flush;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+public class TestCascadingFlush extends SingleEMFTestCase {
+
+    boolean supportsNativeSequence = false;
+
+    public void setUp() {
+        setUp(Assignment.class, ClassPeriod.class, Course.class, SubTopic.class, Topic.class, CLEAR_TABLES);
+
+        try {
+            supportsNativeSequence = ((JDBCConfiguration) emf
+                .getConfiguration()).getDBDictionaryInstance()
+                .nextSequenceQuery != null;
+        } catch (Throwable t) {
+            supportsNativeSequence = false;
+        }
+    }
+
+    /**
+     * Verifies flushing a complex bidirectional domain model results in retrieval and population of all sequence-gen
+     * ID values.
+     */
+    public void testCascadingFlushBasic() {
+        if (!supportsNativeSequence) {
+            return;
+        }
+        EntityManager em = emf.createEntityManager();
+        Long courseId = populate(em);
+        em.clear();
+        Course course = em.find(Course.class, courseId);
+        verifyCascadingFlush(em, course);
+        em.close();
+    }
+
+    /**
+     * Verifies flushing a complex bidirectional domain model results in retrieval and population of all sequence-gen
+     * ID values using an detached, then merged entity graph.
+     */
+    public void testCascadingFlushDetach() {
+        if (!supportsNativeSequence) {
+            return;
+        }
+        EntityManager em = emf.createEntityManager();
+        Long courseId = populate(em);
+        em.clear();
+        Course tmpCourse = em.find(Course.class, courseId);
+
+        Course course = OpenJPAPersistence.cast(em).detach(tmpCourse);
+        assertNotEquals(course, tmpCourse);
+        verifyCascadingFlush(em, course);
+        em.close();
+    }
+
+    /**
+     * Verifies flushing a complex bidirectional domain model results in retrieval of all sequence-gen ID values using
+     * an serialized (resulting in detach), then merged entity graph.
+     */
+    public void testCascadingFlushSerialize() {
+        if (!supportsNativeSequence) {
+            return;
+        }
+        EntityManager em = emf.createEntityManager();
+        try {
+            Long courseId = populate(em);
+            em.clear();
+            Course tmpCourse = em.find(Course.class, courseId);
+            Course course = null;
+            try {
+                course = (Course)roundtrip(tmpCourse, false);
+            } catch (Throwable t) {
+                fail("Failed to serialize and deserialize persistent object.");
+            }
+            assertNotEquals(course, tmpCourse);
+            verifyCascadingFlush(em, course);
+        }
+        finally {
+            if (em != null) {
+                em.close();
+            }
+        }
+    }
+
+
+    private void verifyCascadingFlush(EntityManager em, Course course) {
+        try {
+            beginTx(em);
+            // Add a class period to the graph
+            addClassPeriod(course);
+
+            // Merge in the new entities
+            Course course2 = em.merge(course);
+            // Flush to the database.  ID's should be assigned to all elements in
+            // the graph.
+            em.flush();
+            // Verify all id's are assigned
+            assertTrue(course2.getCourseId() > 0);
+            assertNotNull(course2.getClassPeriods());
+            Set<ClassPeriod> cps = course2.getClassPeriods();
+            assertTrue(cps.size() == 2);
+            for (ClassPeriod cp : cps) {
+                assertNotNull(cp);
+                assertTrue(cp.getClassPeriodId() > 0);
+                assertEquals(cp.getCourse(), course2);
+                Set<Topic> topics = cp.getTopics();
+                assertNotNull(topics);
+                assertTrue(topics.size() > 0);
+                for (Topic t : topics) {
+                    assertNotNull(t);
+                    assertTrue(t.getTopicId() > 0);
+                    Set<Assignment> assignments = t.getAssignments();
+                    assertNotNull(assignments);
+                    assertTrue(assignments.size() == 1);
+                    for (Assignment a : assignments) {
+                        assertNotNull(a);
+                        assertTrue(a.getAssignmentId() > 0);
+                    }
+                    Set<SubTopic> subTopics = t.getSubTopics();
+                    assertNotNull(subTopics);
+                    assertTrue(subTopics.size() == 1);
+                    for (SubTopic s : subTopics) {
+                        assertNotNull(s);
+                        assertTrue(s.getSubtopicId() > 0);
+                    }
+                }
+            }
+
+            commitTx(em);
+        } catch (Exception e) {
+            e.printStackTrace();
+            em.getTransaction().rollback();
+            fail();
+        }
+    }
+
+    public static Long populate(EntityManager em) {
+
+        beginTx(em);
+        Course course = createNewCourse();
+        em.persist(course);
+        em.flush();
+
+        commitTx(em);
+        return course.getCourseId();
+    }
+
+    public static Course createNewCourse() {
+
+        Course course = new Course();
+        course.setCourseText("Nuclear Physics");
+
+        Assignment assignment1 = new Assignment();
+        assignment1.setAssignmentText("Lab: Nuclear Fusion");
+
+        Set<Assignment> assignments = new HashSet<Assignment>();
+        assignments.add(assignment1);
+
+        SubTopic subtopic1 = new SubTopic();
+        subtopic1.setSubtopicText("Nuclear Fusion");
+
+        Set<SubTopic> subtopics = new HashSet<SubTopic>();
+        subtopics.add(subtopic1);
+
+        Topic topic1 = new Topic();
+        topic1.setTopicText("Fundamentals of Nuclear Energy");
+        topic1.setAssignments(assignments);
+        topic1.setSubTopics(subtopics);
+
+        assignment1.setTopic(topic1);
+        subtopic1.setTopic(topic1);
+
+        Set<Topic> topics = new HashSet<Topic>();
+        topics.add(topic1);
+
+        ClassPeriod cp1 = new ClassPeriod();
+        cp1.setClassPeriodText("8844: M,W,Th 8:00AM");
+        cp1.setTopics(topics);
+        cp1.setCourse(course);
+
+        topic1.setClassPeriod(cp1);
+
+        Set<ClassPeriod> cps = new HashSet<ClassPeriod>();
+        cps.add(cp1);
+
+        course.setClassPeriods(cps);
+
+        return course;
+    }
+
+    public static void addClassPeriod(Course course) {
+
+        
+        Assignment assignment = new Assignment();
+        assignment.setAssignmentText("Read pages 442-645");
+
+        Set<Assignment> assignments = new HashSet<Assignment>();
+        assignments.add(assignment);
+
+        SubTopic subTopic = new SubTopic();
+        subTopic.setSubtopicText("Newton");
+
+        Set<SubTopic> subTopics = new HashSet<SubTopic>();
+        subTopics.add(subTopic);
+
+        Topic topic = new Topic();
+        topic.setTopicText("Gravity");
+        topic.setSubTopics(subTopics);
+        topic.setAssignments(assignments);
+
+        assignment.setTopic(topic);
+        subTopic.setTopic(topic);
+
+        Set<Topic> topics = new HashSet<Topic>();
+        topics.add(topic);
+
+        // Add another topic
+        Assignment assignment2 = new Assignment();
+        assignment2.setAssignmentText("Read pages 645-785");
+
+        Set<Assignment> assignments2 = new HashSet<Assignment>();
+        assignments2.add(assignment2);
+
+        SubTopic subTopic2 = new SubTopic();
+        subTopic2.setSubtopicText("Forces");
+
+        Set<SubTopic> subTopics2 = new HashSet<SubTopic>();
+        subTopics2.add(subTopic2);
+
+        Topic topic2 = new Topic();
+        topic2.setTopicText("Magnetism");
+        topic2.setSubTopics(subTopics2);
+        topic2.setAssignments(assignments2);
+
+        subTopic2.setTopic(topic);
+        subTopic2.setTopic(topic);
+
+        topics.add(topic2);
+
+        ClassPeriod cp2 = new ClassPeriod();
+        cp2.setClassPeriodText("8846: M,W,Th 11:00AM");
+        cp2.setTopics(topics);
+        cp2.setCourse(course);
+
+        topic.setClassPeriod(cp2);
+        topic2.setClassPeriod(cp2);
+
+        course.getClassPeriods().add(cp2);
+    }
+
+    private static void beginTx(EntityManager em) {
+        em.getTransaction().begin();
+    }
+
+    private static void commitTx(EntityManager em) {
+        em.getTransaction().commit();
+    }
+
+    public static Object roundtrip(Object orig, boolean validateEquality)
+        throws IOException, ClassNotFoundException {
+        assertNotNull(orig);
+
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream(bout);
+        out.writeObject(orig);
+        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+        ObjectInputStream in = new ObjectInputStream(bin);
+        Object result = in.readObject();
+
+        if (validateEquality) {
+            assertEquals(orig.hashCode(), result.hashCode());
+            assertEquals(orig, result);
+        }
+
+        return result;
+    }
+}

Propchange: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/TestCascadingFlush.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Topic.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Topic.java?rev=1141131&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Topic.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Topic.java Wed Jun 29 15:18:08 2011
@@ -0,0 +1,105 @@
+/*
+ * 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.flush;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
+import org.apache.openjpa.persistence.ElementDependent;
+
+@Entity
+@Table(name="FL_TOPIC")
+public class Topic implements Serializable {
+
+    private static final long serialVersionUID = -2570150606711529060L;
+
+    @Id
+    @Column(name="TOPIC_ID")
+    @SequenceGenerator(name="topicIdSeq", sequenceName="TOPIC_SEQ")
+    @GeneratedValue(generator="topicIdSeq", strategy=GenerationType.SEQUENCE)
+    protected Long topicId;
+    
+    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, fetch=FetchType.LAZY)
+    @JoinColumn(name="CLP_ID")
+    protected ClassPeriod clp;
+
+    @Column(name="TOPIC_TEXT")
+    protected String topicText;
+
+    @OneToMany(mappedBy="topic",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
+    @ElementDependent(true)
+    protected Set<Assignment> assignments;
+    
+    @OneToMany(mappedBy="topic",cascade=CascadeType.ALL, fetch=FetchType.EAGER)
+    @ElementDependent(true)
+    protected Set<SubTopic> subTopics;
+
+    public Long getTopicId() {
+        return topicId;
+    }
+
+    public void setTopicId(Long topicId) {
+        this.topicId = topicId;
+    }
+
+    public ClassPeriod getClassPeriod() {
+        return clp;
+    }
+
+    public void setClassPeriod(ClassPeriod clp) {
+        this.clp = clp;
+    }
+
+    public String getTopicText() {
+        return topicText;
+    }
+
+    public void setTopicText(String topicText) {
+        this.topicText = topicText;
+    }
+
+    public Set<Assignment> getAssignments() {
+        return assignments;
+    }
+
+    public void setAssignments(Set<Assignment> assignments) {
+        this.assignments = assignments;
+    }
+
+    public Set<SubTopic> getSubTopics() {
+        return subTopics;
+    }
+
+    public void setSubTopics(Set<SubTopic> subTopics) {
+        this.subTopics = subTopics;
+    }
+}

Propchange: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/flush/Topic.java
------------------------------------------------------------------------------
    svn:eol-style = native