OPENJPA-692: Detect orphaning relation and change row update to delete for join table entry.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@684822 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2008-08-11 17:18:31 +00:00
parent c8895c6978
commit ffb59c35fc
3 changed files with 69 additions and 4 deletions

View File

@ -73,6 +73,7 @@ public class FieldMapping
private int _fetchMode = Integer.MAX_VALUE;
private Unique[] _joinTableUniques; // Unique constraints on JoinTable
private Boolean _bidirectionalJoinTableOwner = null;
private Boolean _bidirectionalJoinTableNonOwner = null;
/**
* Constructor.
@ -1075,10 +1076,10 @@ public class FieldMapping
ClassMapping relType = elem.getDeclaredTypeMapping();
if (relType == null)
return false;
FieldMetaData[] relFmds = relType.getFields();
FieldMapping[] relFmds = relType.getFieldMappings();
for (int i=0; i<relFmds.length;i++) {
if (relFmds[i].getDeclaredTypeMetaData() == getDeclaringMapping()) {
FieldMapping rfm = (FieldMapping)relFmds[i];
FieldMapping rfm = relFmds[i];
if (rfm.getDeclaredTypeMetaData() == getDeclaringMapping()) {
ForeignKey rjfk = rfm.getJoinForeignKey();
if (rjfk == null)
continue;
@ -1086,9 +1087,55 @@ public class FieldMapping
&& jfk.getTable().getColumns().length
== jfk.getColumns().length + rjfk.getColumns().length) {
_bidirectionalJoinTableOwner = true;
break;
}
}
}
return _bidirectionalJoinTableOwner.booleanValue();
}
/**
* Affirms if this field is the non-owning side of a bidirectional relation
* with a join table. Evaluated only once and the result cached for
* subsequent call. Hence must be called after resolution.
*/
public boolean isBidirectionalJoinTableMappingNonOwner() {
if (_bidirectionalJoinTableNonOwner != null)
return _bidirectionalJoinTableNonOwner.booleanValue();
_bidirectionalJoinTableNonOwner = false;
ForeignKey fk = getForeignKey();
if (fk == null)
return false;
ForeignKey jfk = getJoinForeignKey();
if (jfk == null)
return false;
FieldMapping mappedBy = getValueMappedByMapping();
if (mappedBy != null)
return false;
ValueMapping elem = getElementMapping();
if (elem == null)
return false;
ClassMapping relType = getDeclaredTypeMapping();
if (relType == null)
return false;
FieldMapping[] relFmds = relType.getFieldMappings();
for (int i=0; i<relFmds.length;i++) {
FieldMapping rfm = relFmds[i];
ValueMapping relem = rfm.getElementMapping();
if (relem != null && relem.getDeclaredTypeMapping() == getDeclaringMapping()) {
ForeignKey rjfk = rfm.getJoinForeignKey();
if (rjfk == null)
continue;
if (rjfk.getTable() == jfk.getTable()
&& jfk.getTable().getColumns().length
== jfk.getColumns().length + rjfk.getColumns().length) {
_bidirectionalJoinTableNonOwner = true;
break;
}
}
}
return _bidirectionalJoinTableNonOwner.booleanValue();
}
}

View File

@ -230,7 +230,10 @@ public class RelationFieldStrategy
nullInverse(sm, rm);
updateInverse(sm, rel, store, rm);
} else {
Row row = field.getRow(sm, store, rm, Row.ACTION_UPDATE);
int action = (rel == null
&& field.isBidirectionalJoinTableMappingNonOwner()) ?
Row.ACTION_DELETE : Row.ACTION_UPDATE;
Row row = field.getRow(sm, store, rm, action);
if (row != null)
field.setForeignKey(row, rel);
}

View File

@ -19,6 +19,7 @@
package org.apache.openjpa.persistence.jdbc.mapping.bidi;
import java.util.Arrays;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.Query;
@ -126,6 +127,20 @@ public class TestBiDirectionalJoinTable extends SQLListenerTestCase {
assertSQL("DELETE FROM .*J_PERSON_ADDRESSES .*");
}
public void testBreakingRelationCausesDeleteFromJoinTable() {
EntityManager em = emf.createEntityManager();
Person person = em.find(Person.class, SSN);
em.getTransaction().begin();
Set<Address> addresses = person.getAddresses();
assertFalse(addresses.isEmpty());
Address address = addresses.iterator().next();
addresses.remove(address);
address.setPerson(null);
em.getTransaction().commit();
assertSQL("DELETE FROM .*J_PERSON_ADDRESSES .*");
}
/**
* Create a Person with given SSN and fixed number of addresses.
*