diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java index 46d94180b..7bf3dc0c6 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java @@ -408,8 +408,12 @@ public class RelationFieldStrategy // if our foreign key has a delete action, we need to set the // related object so constraints can be evaluated + Object lastRelPc = sm.fetchObjectField(field.getIndex()); + if( lastRelPc == null) { + lastRelPc = sm.fetchInitialField(field.getIndex()); + } OpenJPAStateManager rel = RelationStrategies.getStateManager - (sm.fetchObjectField(field.getIndex()), store.getContext()); + (lastRelPc, store.getContext()); if (rel != null) { ForeignKey fk = field.getForeignKey((ClassMapping) rel.getMetaData()); diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/Child.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/Child.java new file mode 100644 index 000000000..65fa3aa95 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/Child.java @@ -0,0 +1,82 @@ +/* + * 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.io.Serializable; +import java.util.Collection; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +import org.apache.openjpa.persistence.jdbc.ForeignKey; + +@Entity +@Table(name = "JPAORPHAN_CHILD") +public class Child implements Serializable { + private static final long serialVersionUID = 3974762966445439153L; + + @Id + private int id; + + @ForeignKey + @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.MERGE) + private Parent parent; + + private String name; + + @OneToMany(mappedBy = "child", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) + private Collection grandChilds; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Parent getParent() { + return parent; + } + + public void setParent(Parent parent) { + this.parent = parent; + } + + public Collection getGrandChilds() { + return grandChilds; + } + + public void setGrandChilds(Collection grandChilds) { + this.grandChilds = grandChilds; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/GrandChild.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/GrandChild.java new file mode 100644 index 000000000..9faf07bc3 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/GrandChild.java @@ -0,0 +1,59 @@ +/* + * 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.io.Serializable; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import org.apache.openjpa.persistence.jdbc.ForeignKey; + +@Entity +@Table(name = "JPAORPHAN_GRANDCHILD") +public class GrandChild implements Serializable { + private static final long serialVersionUID = 898044136658616065L; + + @Id + private int id; + + @ForeignKey + @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.MERGE) + private Child child; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Child getChild() { + return child; + } + + public void setChild(Child child) { + this.child = child; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/Parent.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/Parent.java new file mode 100644 index 000000000..0882701dc --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/Parent.java @@ -0,0 +1,57 @@ +/* + * 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.io.Serializable; +import java.util.Collection; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +@Entity +@Table(name = "JPAORPHAN_PARENT") +public class Parent implements Serializable { + private static final long serialVersionUID = -1735171751389872136L; + + @Id + private int id; + + @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) + private Collection childs; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Collection getChilds() { + return childs; + } + + public void setChilds(Collection childs) { + this.childs = childs; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationOrphanRemoval.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationOrphanRemoval.java new file mode 100644 index 000000000..f79decd56 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/relations/TestRelationOrphanRemoval.java @@ -0,0 +1,67 @@ +/* + * 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.Arrays; + +import javax.persistence.EntityTransaction; + +import org.apache.openjpa.persistence.test.SingleEMTestCase; + +public class TestRelationOrphanRemoval extends SingleEMTestCase { + + public void setUp() { + setUp(Parent.class, Child.class, GrandChild.class, CLEAR_TABLES + ); + } + + public void testRelationOrphanRemoval() { + EntityTransaction tx = em.getTransaction(); + + int origId = 10; + int id = origId; + + Parent parent = new Parent(); + parent.setId(id++); + Child child = new Child(); + child.setId(id++); + GrandChild grandChild = new GrandChild(); + grandChild.setId(id++); + parent.setChilds(Arrays.asList(child)); + child.setParent(parent); + child.setGrandChilds(Arrays.asList(grandChild)); + grandChild.setChild(child); + + tx.begin(); + em.persist(parent); + tx.commit(); + + tx.begin(); + parent = em.find(Parent.class, new Integer(origId)); + child = parent.getChilds().iterator().next(); + grandChild = child.getGrandChilds().iterator().next(); + child.setName("Test"); + + grandChild.setChild(null); + child.setGrandChilds(null); + child.setParent(null); + parent.setChilds(null); + tx.commit(); + } +}