mirror of https://github.com/apache/openjpa.git
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:
parent
c8895c6978
commit
ffb59c35fc
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -125,6 +126,20 @@ public class TestBiDirectionalJoinTable extends SQLListenerTestCase {
|
|||
assertEquals(0, count(Address.class));
|
||||
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.
|
||||
|
|
Loading…
Reference in New Issue