OpenJPA-235: merged fix from trunk 673258, "SQL reordering to avoid non-nullable foreign key constraint violations"

git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/1.1.x@802195 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David Ezzio 2009-08-07 21:15:47 +00:00
parent eb934b2ae7
commit 5781d27887
5 changed files with 155 additions and 7 deletions

View File

@ -248,7 +248,8 @@ public class RelationFieldStrategy
if (rel != null) {
ForeignKey fk = field.getForeignKey((ClassMapping)
rel.getMetaData());
if (fk.getDeleteAction() == ForeignKey.ACTION_RESTRICT) {
if (fk.getDeleteAction() == ForeignKey.ACTION_RESTRICT ||
fk.getDeleteAction() == ForeignKey.ACTION_CASCADE) {
Row row = field.getRow(sm, store, rm, Row.ACTION_DELETE);
row.setForeignKey(fk, null, rel);
}

View File

@ -192,10 +192,10 @@ public class PrimaryRow
}
/**
* If this is a delete, delay foreign keys to other deleted objects if
* the key is restricted. If this is an update or insert, delay foreign
* keys to other inserts if the key is not logical. If the foreign key
* is to a new record and the columns are auto-inc, record it.
* If this is a delete, delay foreign keys to other deleted objects if the
* key is restricted or cascade. If this is an update or insert, delay
* foreign keys to other inserts if the key is not logical. If the foreign
* key is to a new record and the columns are auto-inc, record it.
*/
private boolean delayForeignKey(ForeignKey fk, OpenJPAStateManager sm,
boolean set) {
@ -204,7 +204,8 @@ public class PrimaryRow
if (getAction() == ACTION_DELETE)
return sm.isDeleted() && !fk.isDeferred()
&& fk.getDeleteAction() == ForeignKey.ACTION_RESTRICT;
&& (fk.getDeleteAction() == ForeignKey.ACTION_RESTRICT ||
fk.getDeleteAction() == ForeignKey.ACTION_CASCADE);
if (!sm.isNew() || sm.isFlushed())
return false;

View File

@ -0,0 +1,43 @@
/*
* 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.jdbc.kernel;
import java.util.List;
import javax.persistence.*;
@Entity
public class EntityF {
@Id private int id;
@OneToMany(cascade=CascadeType.ALL, mappedBy="entityF")
private List<EntityG> listG;
public List<EntityG> getListG() {
return listG;
}
public void setListG(List<EntityG> listG) {
this.listG = listG;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.jdbc.kernel;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.apache.openjpa.persistence.jdbc.ForeignKey;
import org.apache.openjpa.persistence.jdbc.ForeignKeyAction;
@Entity
public class EntityG {
@Id private int id;
@ForeignKey(deleteAction=ForeignKeyAction.CASCADE)
@ManyToOne (cascade=CascadeType.MERGE)
private EntityF entityF;
public EntityF getEntityF() {
return entityF;
}
public void setEntityF(EntityF entityF) {
this.entityF = entityF;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}

View File

@ -18,6 +18,8 @@
*/
package org.apache.openjpa.jdbc.kernel;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
@ -37,7 +39,8 @@ public class TestNoForeignKeyViolation
private EntityD entityD;
public void setUp() {
setUp(EntityA.class, EntityB.class, EntityC.class, EntityD.class, EntityE.class);
setUp(EntityA.class, EntityB.class, EntityC.class, EntityD.class,
EntityE.class, EntityF.class, EntityG.class);
createTestData();
}
@ -154,4 +157,55 @@ public class TestNoForeignKeyViolation
em.close();
}
}
public void testForeignKeyCascade() {
EntityManager em = emf.createEntityManager();
try {
EntityF f = new EntityF();
f.setId(1);
List<EntityG> listG = new ArrayList<EntityG>();
EntityG g1 = new EntityG();
g1.setId(1);
listG.add(g1);
g1.setEntityF(f);
EntityG g2 = new EntityG();
g2.setId(2);
listG.add(g2);
g2.setEntityF(f);
EntityG g3 = new EntityG();
g3.setId(3);
listG.add(g3);
g3.setEntityF(f);
EntityG g4 = new EntityG();
g4.setId(4);
listG.add(g4);
g4.setEntityF(f);
f.setListG(listG);
em.getTransaction().begin();
em.persist(f);
em.persist(g1);
em.persist(g2);
em.persist(g3);
em.persist(g4);
em.getTransaction().commit();
em.getTransaction().begin();
em.remove(f);
em.getTransaction().commit();
}
catch (Exception e) {
fail("Fail to delete EntityF");
}
finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
em.close();
}
}
}