Author: ppoddar
Date: Mon Aug 11 10:18:31 2008
New Revision: 684822
URL:
http://svn.apache.org/viewvc?rev=684822&view=revLog:
OPENJPA-692: Detect orphaning relation and change row update to delete for join table entry.
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/mapping/bidi/TestBiDirectionalJoinTable.java
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java?rev=684822&r1=684821&r2=684822&view=diff==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java Mon Aug 11 10:18:31 2008
@@ -73,6 +73,7 @@
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 @@
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 @@
&& 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();
+ }
+
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java?rev=684822&r1=684821&r2=684822&view=diff==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java Mon Aug 11 10:18:31 2008
@@ -230,7 +230,10 @@
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);
}
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/mapping/bidi/TestBiDirectionalJoinTable.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/mapping/bidi/TestBiDirectionalJoinTable.java?rev=684822&r1=684821&r2=684822&view=diff==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/mapping/bidi/TestBiDirectionalJoinTable.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/mapping/bidi/TestBiDirectionalJoinTable.java Mon Aug 11 10:18:31 2008
@@ -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 @@
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.