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 int _fetchMode = Integer.MAX_VALUE;
|
||||||
private Unique[] _joinTableUniques; // Unique constraints on JoinTable
|
private Unique[] _joinTableUniques; // Unique constraints on JoinTable
|
||||||
private Boolean _bidirectionalJoinTableOwner = null;
|
private Boolean _bidirectionalJoinTableOwner = null;
|
||||||
|
private Boolean _bidirectionalJoinTableNonOwner = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
|
@ -1075,10 +1076,10 @@ public class FieldMapping
|
||||||
ClassMapping relType = elem.getDeclaredTypeMapping();
|
ClassMapping relType = elem.getDeclaredTypeMapping();
|
||||||
if (relType == null)
|
if (relType == null)
|
||||||
return false;
|
return false;
|
||||||
FieldMetaData[] relFmds = relType.getFields();
|
FieldMapping[] relFmds = relType.getFieldMappings();
|
||||||
for (int i=0; i<relFmds.length;i++) {
|
for (int i=0; i<relFmds.length;i++) {
|
||||||
if (relFmds[i].getDeclaredTypeMetaData() == getDeclaringMapping()) {
|
FieldMapping rfm = relFmds[i];
|
||||||
FieldMapping rfm = (FieldMapping)relFmds[i];
|
if (rfm.getDeclaredTypeMetaData() == getDeclaringMapping()) {
|
||||||
ForeignKey rjfk = rfm.getJoinForeignKey();
|
ForeignKey rjfk = rfm.getJoinForeignKey();
|
||||||
if (rjfk == null)
|
if (rjfk == null)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1086,9 +1087,55 @@ public class FieldMapping
|
||||||
&& jfk.getTable().getColumns().length
|
&& jfk.getTable().getColumns().length
|
||||||
== jfk.getColumns().length + rjfk.getColumns().length) {
|
== jfk.getColumns().length + rjfk.getColumns().length) {
|
||||||
_bidirectionalJoinTableOwner = true;
|
_bidirectionalJoinTableOwner = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _bidirectionalJoinTableOwner.booleanValue();
|
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);
|
nullInverse(sm, rm);
|
||||||
updateInverse(sm, rel, store, rm);
|
updateInverse(sm, rel, store, rm);
|
||||||
} else {
|
} 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)
|
if (row != null)
|
||||||
field.setForeignKey(row, rel);
|
field.setForeignKey(row, rel);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.apache.openjpa.persistence.jdbc.mapping.bidi;
|
package org.apache.openjpa.persistence.jdbc.mapping.bidi;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
|
@ -126,6 +127,20 @@ public class TestBiDirectionalJoinTable extends SQLListenerTestCase {
|
||||||
assertSQL("DELETE FROM .*J_PERSON_ADDRESSES .*");
|
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.
|
* Create a Person with given SSN and fixed number of addresses.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue