mirror of https://github.com/apache/openjpa.git
OPENJPA-2006: If flushing, also pre-flush non-provisional entities to allow sequence ID population - merged Jeremy's changes from trunk.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/2.0.x@1141193 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2ede6e480c
commit
49f14ecdeb
|
@ -5075,4 +5075,8 @@ public class BrokerImpl
|
||||||
}
|
}
|
||||||
return _store.isCached(oids, loaded);
|
return _store.isCached(oids, loaded);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected boolean isFlushing() {
|
||||||
|
return ((_flags & FLAG_FLUSHING) != 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -782,6 +782,12 @@ class SingleFieldManager
|
||||||
// ensure generated IDs get assigned properly
|
// ensure generated IDs get assigned properly
|
||||||
if (!logical)
|
if (!logical)
|
||||||
((StateManagerImpl)sm).assignObjectId(false, true);
|
((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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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).detachCopy(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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue