You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2009/09/26 15:42:20 UTC
svn commit: r819139 - in /openjpa/trunk:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/
Author: faywang
Date: Sat Sep 26 13:42:19 2009
New Revision: 819139
URL: http://svn.apache.org/viewvc?rev=819139&view=rev
Log:
OPENJPA-1253: support foreign key strategy for uni-directional one to many mapping using Map with entity as the Map key.
Added:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_RelKey_FK.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/Uni_1ToM_Map_RelKey_FK.java
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMappingInfo.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingInfo.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMappingInfo.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMappingInfo.java?rev=819139&r1=819138&r2=819139&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMappingInfo.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMappingInfo.java Sat Sep 26 13:42:19 2009
@@ -23,6 +23,7 @@
import java.util.List;
import org.apache.openjpa.conf.Compatibility;
+import org.apache.openjpa.jdbc.meta.strats.MapTableFieldStrategy;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.ColumnIO;
import org.apache.openjpa.jdbc.schema.ForeignKey;
@@ -147,6 +148,17 @@
}, schemaName, tableName, adapt);
}
+ public ForeignKey getJoinForeignKey (final FieldMapping field, Table table,
+ boolean adapt) {
+ Strategy strat = field.getStrategy();
+ if (strat instanceof MapTableFieldStrategy &&
+ ((MapTableFieldStrategy)strat).isUni1ToMFK()) {
+ List cols = field.getElementMapping().getValueInfo().getColumns();
+ return getJoin(field, table, adapt, cols);
+ }
+ return null;
+ }
+
/**
* Return the join from the field table to the owning class table.
*/
@@ -154,7 +166,11 @@
boolean adapt) {
// if we have no join columns defined, check class-level join
// if the given field is embedded then consider primary table of owner
- List cols = getColumns();
+ return getJoin(field, table, adapt, getColumns());
+ }
+
+ public ForeignKey getJoin(final FieldMapping field, Table table,
+ boolean adapt, List cols) {
if (cols.isEmpty()) {
ClassMapping mapping;
if (field.isEmbedded() &&
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingInfo.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingInfo.java?rev=819139&r1=819138&r2=819139&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingInfo.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ValueMappingInfo.java Sat Sep 26 13:42:19 2009
@@ -107,7 +107,7 @@
getDefiningMapping(), rel, inversable, adapt);
}
- private Table getTable(ValueMapping val) {
+ public Table getTable(ValueMapping val) {
FieldMapping field = val.getFieldMapping();
Table table = field.getTable();
if (table == null) {
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java?rev=819139&r1=819138&r2=819139&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java Sat Sep 26 13:42:19 2009
@@ -150,7 +150,7 @@
// map to the owner table
handleMappedByForeignKey(adapt);
} else if ((!isUni1ToMFK() && isBi1ToMJT()) ||
- (!isUni1ToMFK() && !isBi1ToMJT() && mapped == null)){
+ (!isUni1ToMFK() && !isBi1ToMJT() && mapped == null)) {
// map to a separate table
field.mapJoin(adapt, true);
if (val.getTypeMapping().isMapped()) {
@@ -306,29 +306,21 @@
for (Iterator itr = rem.iterator(); itr.hasNext();) {
mkey = itr.next();
if (isUni1ToMFK()){
- delRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
- Row.ACTION_UPDATE, sm, true);
- val.setForeignKey(delRow, null);
- }
-
- HandlerStrategies.where(key, mkey, store, delRow,
- _kcols);
- if (!isUni1ToMFK())
+ updateSetNull(sm, mkey, store, rm);
+ } else {
+ HandlerStrategies.where(key, mkey, store, delRow, _kcols);
rm.flushSecondaryRow(delRow);
+ }
}
if (!canChange && !change.isEmpty()) {
for (Iterator itr = change.iterator(); itr.hasNext();) {
mkey = itr.next();
if (isUni1ToMFK()){
- delRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
- Row.ACTION_UPDATE, sm, true);
- val.setForeignKey(delRow, null);
- }
-
- HandlerStrategies.where(key, itr.next(), store, delRow,
- _kcols);
- if (!isUni1ToMFK())
+ updateSetNull(sm, mkey, store, rm);
+ } else {
+ HandlerStrategies.where(key, itr.next(), store, delRow, _kcols);
rm.flushSecondaryRow(delRow);
+ }
}
}
}
@@ -422,8 +414,38 @@
public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
- if ((field.getMappedBy() != null && !isBi1ToMJT()) || isUni1ToMFK())
+ if ((field.getMappedBy() != null && !isBi1ToMJT()))
return;
+ if (isUni1ToMFK()) {
+ Map mapObj = (Map)sm.fetchObject(field.getIndex());
+ updateSetNull(sm, store, rm, mapObj.keySet());
+ return;
+ }
+
super.delete(sm, store, rm);
}
+
+ private void updateSetNull(OpenJPAStateManager sm, JDBCStore store, RowManager rm,
+ Set rem) throws SQLException {
+ for (Iterator itr = rem.iterator(); itr.hasNext();) {
+ Object mkey = itr.next();
+ updateSetNull(sm, mkey, store, rm);
+ }
+ }
+
+ private void updateSetNull(OpenJPAStateManager sm, Object mkey,
+ JDBCStore store, RowManager rm) throws SQLException {
+ ValueMapping key = field.getKeyMapping();
+ ValueMapping val = field.getElementMapping();
+ StoreContext ctx = store.getContext();
+ ValueMappingInfo vinfo = field.getElementMapping().getValueInfo();
+ Table table = vinfo.getTable(val);
+ ForeignKey joinFK = field.getMappingInfo().getJoinForeignKey(field, table, true);
+ Row delRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+ Row.ACTION_UPDATE, sm, true);
+ delRow.whereForeignKey(joinFK, sm);
+ val.setForeignKey(delRow, null);
+ HandlerStrategies.set(key, null, store, delRow, _kcols, _kio, true);
+ HandlerStrategies.where(key, mkey, store, delRow, _kcols);
+ }
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java?rev=819139&r1=819138&r2=819139&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java Sat Sep 26 13:42:19 2009
@@ -99,13 +99,13 @@
}
- protected boolean isBi1ToMJT() {
+ public boolean isBi1ToMJT() {
if (_isBi1ToMJT == null)
isNonDefaultMapping();
return _isBi1ToMJT;
}
- protected boolean isUni1ToMFK() {
+ public boolean isUni1ToMFK() {
if (_isUni1ToMFK == null)
isNonDefaultMapping();
return _isUni1ToMFK;
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java?rev=819139&r1=819138&r2=819139&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java Sat Sep 26 13:42:19 2009
@@ -80,7 +80,17 @@
kunion.setLRS(lrs);
kunion.select(new Union.Selector() {
public void select(Select sel, int idx) {
- sel.whereForeignKey(field.getJoinForeignKey(),
+ ForeignKey joinFK = null;
+ if (isUni1ToMFK()) {
+ ValueMapping val = field.getElementMapping();
+ ValueMappingInfo vinfo = val.getValueInfo();
+ Table table = vinfo.getTable(val);
+ joinFK = field.getMappingInfo().getJoinForeignKey(field, table, true);
+ } else {
+ joinFK = field.getJoinForeignKey();
+ }
+
+ sel.whereForeignKey(joinFK,
sm.getObjectId(), field.getDefiningMapping(), store);
// order before select in case we're faking union with
@@ -106,21 +116,29 @@
vunion.setLRS(lrs);
vunion.select(new Union.Selector() {
public void select(Select sel, int idx) {
- sel.whereForeignKey(field.getJoinForeignKey(),
- sm.getObjectId(), field.getDefiningMapping(), store);
-
- // order before select in case we're faking union with
- // multiple selects; order vals used to merge results
- FieldMapping mapped = field.getMappedByMapping();
- Joins joins = joinValueRelation(sel.newJoins(), vals[idx]);
- sel.orderBy(field.getKeyMapping().getColumns(), true, true);
- sel.select(vals[idx], field.getElementMapping().
- getSelectSubclasses(), store, fetch, eagerMode, joins);
-
- //### cheat: result joins only care about the relation path;
- //### thus we can use first mapping of union only
- if (idx == 0)
- resJoins[1] = joins;
+ if (isUni1ToMFK()) {
+ sel.orderBy(field.getKeyMapping().getColumns(), true, true);
+ sel.select(vals[idx], field.getElementMapping().
+ getSelectSubclasses(), store, fetch, eagerMode, null);
+ sel.whereForeignKey(field.getElementMapping().getForeignKey(),
+ sm.getObjectId(), field.getElementMapping().getDeclaredTypeMapping(), store);
+
+ } else {
+ sel.whereForeignKey(field.getJoinForeignKey(),
+ sm.getObjectId(), field.getDefiningMapping(), store);
+
+ // order before select in case we're faking union with
+ // multiple selects; order vals used to merge results
+ Joins joins = joinValueRelation(sel.newJoins(), vals[idx]);
+ sel.orderBy(field.getKeyMapping().getColumns(), true, true);
+ sel.select(vals[idx], field.getElementMapping().
+ getSelectSubclasses(), store, fetch, eagerMode, joins);
+
+ //### cheat: result joins only care about the relation path;
+ //### thus we can use first mapping of union only
+ if (idx == 0)
+ resJoins[1] = joins;
+ }
}
});
@@ -184,10 +202,12 @@
FieldMapping mapped = field.getMappedByMapping();
DBDictionary dict = field.getMappingRepository().getDBDictionary();
String keyName = null;
- if (mapped != null) {
+ if ((isUni1ToMFK() && !isBi1ToMJT()) ||
+ (!isUni1ToMFK() && !isBi1ToMJT() && mapped != null)) {
handleMappedByForeignKey(adapt);
keyName = dict.getValidColumnName("vkey", field.getTable());
- } else {
+ } else if ((!isUni1ToMFK() && isBi1ToMJT()) ||
+ (!isUni1ToMFK() && !isBi1ToMJT() && mapped == null)) {
field.mapJoin(adapt, true);
mapTypeJoin(val, "value", adapt);
keyName = dict.getValidColumnName("key", field.getTable());
@@ -226,13 +246,15 @@
if (map == null || map.isEmpty())
return;
- if (field.getMappedBy() != null)
+ if (!isBi1ToMJT() && field.getMappedBy() != null)
return;
- Row row = rm.getSecondaryRow(field.getTable(), Row.ACTION_INSERT);
- row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(),
- sm);
-
+ Row row = null;
+ if (!isUni1ToMFK()) {
+ row = rm.getSecondaryRow(field.getTable(), Row.ACTION_INSERT);
+ row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(),
+ sm);
+ }
ValueMapping key = field.getKeyMapping();
ValueMapping val = field.getElementMapping();
StoreContext ctx = sm.getContext();
@@ -242,10 +264,17 @@
entry = (Map.Entry) itr.next();
keysm = RelationStrategies.getStateManager(entry.getKey(), ctx);
valsm = RelationStrategies.getStateManager(entry.getValue(), ctx);
+ if (isUni1ToMFK()){
+ row = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+ Row.ACTION_UPDATE, valsm, true);
+ row.wherePrimaryKey(valsm);
+ val.setForeignKey(row, sm);
+ } else {
+ val.setForeignKey(row, valsm);
+ }
key.setForeignKey(row, keysm);
- val.setForeignKey(row, valsm);
- // so far, we poplulated the key/value of each
+ // so far, we populated the key/value of each
// map element owned by the entity.
// In the case of ToMany, and both sides
// use Map to represent the relation,
@@ -253,13 +282,14 @@
// from the view point of the owned side
PersistenceCapable obj = sm.getPersistenceCapable();
if (!populateKey(row, valsm, obj, ctx, rm, store))
- rm.flushSecondaryRow(row);
+ if (!isUni1ToMFK())
+ rm.flushSecondaryRow(row);
}
}
public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
- if (field.getMappedBy() != null)
+ if (field.getMappedBy() != null && !isBi1ToMJT())
return;
Map map = (Map) sm.fetchObject(field.getIndex());
@@ -289,38 +319,69 @@
boolean canChange = val.getForeignKey().isLogical();
Object mkey;
if (canChange && !change.isEmpty()) {
- Row changeRow = rm.getSecondaryRow(field.getTable(),
- Row.ACTION_UPDATE);
- changeRow.whereForeignKey(field.getJoinForeignKey(), sm);
-
+ Row changeRow = null;
+ if (!isUni1ToMFK()) {
+ rm.getSecondaryRow(field.getTable(),
+ Row.ACTION_UPDATE);
+ changeRow.whereForeignKey(field.getJoinForeignKey(), sm);
+ }
for (Iterator itr = change.iterator(); itr.hasNext();) {
mkey = itr.next();
+ Object mval = map.get(mkey);
+ if (mval == null) {
+ Set<Map.Entry> entries = map.entrySet();
+ for (Map.Entry entry : entries) {
+ if (entry.getKey().equals(mkey))
+ mval = entry.getValue();
+ }
+ }
+ if (mval == null)
+ continue;
keysm = RelationStrategies.getStateManager(mkey, ctx);
- valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
+ valsm = RelationStrategies.getStateManager(mval, ctx);
key.whereForeignKey(changeRow, keysm);
- val.setForeignKey(changeRow, valsm);
- rm.flushSecondaryRow(changeRow);
+ if (isUni1ToMFK()){
+ changeRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+ Row.ACTION_UPDATE, valsm, true);
+ changeRow.wherePrimaryKey(valsm);
+ val.setForeignKey(changeRow, sm);
+ } else {
+ val.setForeignKey(changeRow, valsm);
+ rm.flushSecondaryRow(changeRow);
+ }
}
}
// delete the removes
Collection rem = ct.getRemoved();
if (!rem.isEmpty() || (!canChange && !change.isEmpty())) {
- Row delRow = rm.getSecondaryRow(field.getTable(),
- Row.ACTION_DELETE);
- delRow.whereForeignKey(field.getJoinForeignKey(), sm);
+ Row delRow = null;
+ if (!isUni1ToMFK()) {
+ delRow = rm.getSecondaryRow(field.getTable(),
+ Row.ACTION_DELETE);
+ delRow.whereForeignKey(field.getJoinForeignKey(), sm);
+ }
for (Iterator itr = rem.iterator(); itr.hasNext();) {
- keysm = RelationStrategies.getStateManager(itr.next(), ctx);
- key.whereForeignKey(delRow, keysm);
- rm.flushSecondaryRow(delRow);
+ Object pc = itr.next();
+ if (isUni1ToMFK()){
+ updateSetNull(sm, rm, pc);
+ } else {
+ keysm = RelationStrategies.getStateManager(pc, ctx);
+ key.whereForeignKey(delRow, keysm);
+ rm.flushSecondaryRow(delRow);
+ }
}
if (!canChange && !change.isEmpty()) {
for (Iterator itr = change.iterator(); itr.hasNext();) {
- keysm = RelationStrategies.getStateManager(itr.next(),
- ctx);
- key.whereForeignKey(delRow, keysm);
- rm.flushSecondaryRow(delRow);
+ Object pc = itr.next();
+ if (isUni1ToMFK()){
+ updateSetNull(sm, rm, pc);
+ } else {
+ keysm = RelationStrategies.getStateManager(pc, ctx);
+ key.whereForeignKey(delRow, keysm);
+ rm.flushSecondaryRow(delRow);
+ }
}
}
}
@@ -328,28 +389,65 @@
// insert the adds
Collection add = ct.getAdded();
if (!add.isEmpty() || (!canChange && !change.isEmpty())) {
- Row addRow = rm.getSecondaryRow(field.getTable(),
- Row.ACTION_INSERT);
- addRow.setForeignKey(field.getJoinForeignKey(),
- field.getJoinColumnIO(), sm);
-
+ Row addRow = null;
+ if (!isUni1ToMFK()) {
+ addRow = rm.getSecondaryRow(field.getTable(),
+ Row.ACTION_INSERT);
+ addRow.setForeignKey(field.getJoinForeignKey(),
+ field.getJoinColumnIO(), sm);
+ }
for (Iterator itr = add.iterator(); itr.hasNext();) {
mkey = itr.next();
+ Object mval = map.get(mkey);
+ if (mval == null) {
+ Set<Map.Entry> entries = map.entrySet();
+ for (Map.Entry entry : entries) {
+ if (entry.getKey().equals(mkey))
+ mval = entry.getValue();
+ }
+ }
+ if (mval == null)
+ continue;
keysm = RelationStrategies.getStateManager(mkey, ctx);
- valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
- key.setForeignKey(addRow, keysm);
- val.setForeignKey(addRow, valsm);
- rm.flushSecondaryRow(addRow);
+ valsm = RelationStrategies.getStateManager(mval, ctx);
+ if (isUni1ToMFK()){
+ addRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+ Row.ACTION_UPDATE, valsm, true);
+ addRow.wherePrimaryKey(valsm);
+ key.setForeignKey(addRow, keysm);
+ val.setForeignKey(addRow, sm);
+ } else {
+ key.setForeignKey(addRow, keysm);
+ val.setForeignKey(addRow, valsm);
+ rm.flushSecondaryRow(addRow);
+ }
}
if (!canChange && !change.isEmpty()) {
for (Iterator itr = change.iterator(); itr.hasNext();) {
mkey = itr.next();
+ Object mval = map.get(mkey);
+ if (mval == null) {
+ Set<Map.Entry> entries = map.entrySet();
+ for (Map.Entry entry : entries) {
+ if (entry.getKey().equals(mkey))
+ mval = entry.getValue();
+ }
+ }
+ if (mval == null)
+ continue;
keysm = RelationStrategies.getStateManager(mkey, ctx);
- valsm = RelationStrategies.getStateManager(map.get(mkey),
- ctx);
- key.setForeignKey(addRow, keysm);
- val.setForeignKey(addRow, valsm);
- rm.flushSecondaryRow(addRow);
+ valsm = RelationStrategies.getStateManager(mval, ctx);
+ if (isUni1ToMFK()){
+ addRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+ Row.ACTION_UPDATE, valsm, true);
+ addRow.wherePrimaryKey(valsm);
+ key.setForeignKey(addRow, keysm);
+ val.setForeignKey(addRow, sm);
+ } else {
+ key.setForeignKey(addRow, keysm);
+ val.setForeignKey(addRow, valsm);
+ rm.flushSecondaryRow(addRow);
+ }
}
}
}
@@ -403,4 +501,39 @@
return RelationStrategies.toDataStoreValue(field.getKeyMapping(),
val, store);
}
+
+ public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+ throws SQLException {
+ if (isUni1ToMFK()) {
+ Map mapObj = (Map)sm.fetchObject(field.getIndex());
+ updateSetNull(sm, store, rm, mapObj.keySet());
+ return;
+ }
+ super.delete(sm, store, rm);
+ }
+
+ private void updateSetNull(OpenJPAStateManager sm, JDBCStore store, RowManager rm,
+ Set rem) throws SQLException {
+ for (Iterator itr = rem.iterator(); itr.hasNext();) {
+ Object mkey = itr.next();
+ updateSetNull(sm, rm, mkey);
+ }
+ }
+
+ private void updateSetNull(OpenJPAStateManager sm, RowManager rm, Object mkey)
+ throws SQLException {
+ StoreContext ctx = sm.getContext();
+ ValueMapping key = field.getKeyMapping();
+ ValueMapping val = field.getElementMapping();
+ OpenJPAStateManager keysm = RelationStrategies.getStateManager(mkey, ctx);
+ Row delRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
+ Row.ACTION_UPDATE, sm, true);
+ ValueMappingInfo vinfo = field.getElementMapping().getValueInfo();
+ Table table = vinfo.getTable(val);
+ ForeignKey joinFK = field.getMappingInfo().getJoinForeignKey(field, table, true);
+ delRow.whereForeignKey(joinFK, sm);
+ delRow.whereForeignKey(key.getForeignKey(), keysm);
+ val.setForeignKey(delRow, null);
+ key.setForeignKey(delRow, null);
+ }
}
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC.java?rev=819139&r1=819138&r2=819139&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC.java Sat Sep 26 13:42:19 2009
@@ -44,4 +44,17 @@
public void setName(String name) {
this.name = name;
}
+
+ public int hashCode() {
+ return name.hashCode() + (int)id;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof EntityC)) return false;
+ EntityC c = (EntityC)o;
+ if (!c.name.equals(name)) return false;
+ if (c.id != id) return false;
+ return true;
+ }
+
}
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_RelKey_FK.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_RelKey_FK.java?rev=819139&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_RelKey_FK.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/EntityC_U1M_Map_RelKey_FK.java Sat Sep 26 13:42:19 2009
@@ -0,0 +1,61 @@
+/*
+ * 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.persistence.compat;
+
+import java.util.List;
+
+import javax.persistence.*;
+
+@Entity
+public class EntityC_U1M_Map_RelKey_FK {
+
+ @Id
+ @GeneratedValue
+ private long id;
+
+ private String name;
+
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int hashCode() {
+ return name.hashCode() + (int)id;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof EntityC_U1M_Map_RelKey_FK)) return false;
+ EntityC_U1M_Map_RelKey_FK c = (EntityC_U1M_Map_RelKey_FK)o;
+ if (!c.name.equals(name)) return false;
+ if (c.id != id) return false;
+ return true;
+ }
+
+ public String toString() {
+ return id + name;
+ }
+}
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java?rev=819139&r1=819138&r2=819139&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java Sat Sep 26 13:42:19 2009
@@ -341,7 +341,6 @@
em.clear();
}
- // non default
public void crudBi1MJT(EntityManager em) {
Bi_1ToM_JT b = new Bi_1ToM_JT();
b.setName("bi1mfk");
@@ -398,6 +397,9 @@
types.add(Uni_1ToM_Map_FK.class);
types.add(EntityC_B1M_Map_JT.class);
types.add(Bi_1ToM_Map_JT.class);
+ types.add(EntityC_U1M_Map_RelKey_FK.class);
+ types.add(Uni_1ToM_Map_RelKey_FK.class);
+ types.add(EntityC.class);
OpenJPAEntityManagerFactorySPI emf = createEMF2_0(types);
EntityManager em = emf.createEntityManager();
@@ -408,6 +410,7 @@
assertSQLFragnments(sql, "CREATE TABLE EntityC_U1M_Map_FK", "Uni1MFK_ID", "KEY0");
crudUni1MMapFK(em);
crudBi1MMapJT(em);
+ crudUni1MMapRelKeyFK(em);
} catch (Exception e) {
e.printStackTrace();
fail("OneToMany mapping failed with exception message: " + e.getMessage());
@@ -526,6 +529,74 @@
em.getTransaction().commit();
}
+ public void crudUni1MMapRelKeyFK(EntityManager em) {
+ //create
+ Uni_1ToM_Map_RelKey_FK u = new Uni_1ToM_Map_RelKey_FK();
+ u.setName("uni1mfk");
+ Map<EntityC, EntityC_U1M_Map_RelKey_FK> cs = new HashMap<EntityC, EntityC_U1M_Map_RelKey_FK>();
+ EntityC_U1M_Map_RelKey_FK c1 = new EntityC_U1M_Map_RelKey_FK();
+ c1.setName("c1");
+ EntityC cKey1 = new EntityC();
+ cKey1.setName("cKey1");
+ cs.put(cKey1, c1);
+ EntityC_U1M_Map_RelKey_FK c2 = new EntityC_U1M_Map_RelKey_FK();
+ c2.setName("c2");
+ EntityC cKey2 = new EntityC();
+ cKey2.setName("cKey2");
+ cs.put(cKey2, c1);
+ cs.put(cKey2, c2);
+ u.setEntityCs(cs);
+ em.persist(u);
+ em.persist(c1);
+ em.persist(c2);
+ em.persist(cKey1);
+ em.persist(cKey2);
+ em.getTransaction().begin();
+ em.getTransaction().commit();
+
+ //update by adding a new C
+ em.getTransaction().begin();
+ cs = u.getEntityCs();
+ u.setName("uni1mfk_new");
+ EntityC_U1M_Map_RelKey_FK c3 = new EntityC_U1M_Map_RelKey_FK();
+ c3.setName("c3");
+ EntityC cKey3 = new EntityC();
+ cKey3.setName("cKey3");
+ cs.put(cKey3, c3);
+ em.persist(c3);
+ em.persist(cKey3);
+ em.getTransaction().commit();
+
+ // update by removing a c and then add this c to a new u
+ em.getTransaction().begin();
+ EntityC_U1M_Map_RelKey_FK c4 = cs.remove(cKey1);
+
+ Uni_1ToM_Map_RelKey_FK u2 = new Uni_1ToM_Map_RelKey_FK();
+ u2.setName("uni1mfk2");
+ Map<EntityC, EntityC_U1M_Map_RelKey_FK> cs2 = new HashMap<EntityC, EntityC_U1M_Map_RelKey_FK>();
+ cs2.put(cKey1, c4);
+ u2.setEntityCs(cs2);
+ em.persist(u2);
+ em.getTransaction().commit();
+ em.clear();
+
+ //query
+ Query q = em.createQuery("SELECT u FROM Uni_1ToM_Map_RelKey_FK u where u.name='uni1mfk_new'");
+ Uni_1ToM_Map_RelKey_FK u1 = (Uni_1ToM_Map_RelKey_FK)q.getSingleResult();
+ assertEquals(u, u1);
+ em.clear();
+
+ //find
+ long id = u1.getId();
+ Uni_1ToM_Map_RelKey_FK findU = em.find(Uni_1ToM_Map_RelKey_FK.class, id);
+ assertEquals(u, findU);
+
+ //remove
+ em.getTransaction().begin();
+ em.remove(findU);
+ em.getTransaction().commit();
+ }
+
private OpenJPAEntityManagerFactorySPI createEMF2_0(List<Class<?>> types) {
Map<Object,Object> map = new HashMap<Object,Object>();
map.put("openjpa.jdbc.JDBCListeners",
Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/Uni_1ToM_Map_RelKey_FK.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/Uni_1ToM_Map_RelKey_FK.java?rev=819139&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/Uni_1ToM_Map_RelKey_FK.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/Uni_1ToM_Map_RelKey_FK.java Sat Sep 26 13:42:19 2009
@@ -0,0 +1,97 @@
+/*
+ * 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.persistence.compat;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.*;
+
+//non-default mapping
+//Sec 11.1.36, Example 3:
+// Unidirectional One-to-Many association using a foreign key mapping
+// In Customer class:
+// @OneToMany(orphanRemoval=true)
+// @JoinColumn(name="CUST_ID") // join column is in table for Order
+// public Set<Order> getOrders() {return orders;}
+
+@Entity
+public class Uni_1ToM_Map_RelKey_FK {
+
+ @Id
+ @GeneratedValue
+ private long id;
+
+ private String name;
+
+ @OneToMany(/*cascade = CascadeType.ALL,*/ fetch=FetchType.EAGER)
+ @JoinColumn(name="Uni1MFK_ID")
+ private Map<EntityC, EntityC_U1M_Map_RelKey_FK> entityCs = null;
+
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Map<EntityC, EntityC_U1M_Map_RelKey_FK> getEntityCs() {
+ return entityCs;
+ }
+
+ public void setEntityCs(Map<EntityC, EntityC_U1M_Map_RelKey_FK> entityCs) {
+ this.entityCs = entityCs;
+ }
+
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof Uni_1ToM_Map_RelKey_FK)) return false;
+ Uni_1ToM_Map_RelKey_FK b = (Uni_1ToM_Map_RelKey_FK)o;
+ if (!b.name.equals(name)) return false;
+ if (b.entityCs.size() != entityCs.size()) return false;
+
+ Set<EntityC> coll = b.entityCs.keySet();
+ for (EntityC cKey : coll) {
+ EntityC_U1M_Map_RelKey_FK val = (EntityC_U1M_Map_RelKey_FK)getValue(b.entityCs, cKey);
+ EntityC_U1M_Map_RelKey_FK val1 = (EntityC_U1M_Map_RelKey_FK)getValue(entityCs, cKey);
+ if (!val.equals(val1))
+ return false;
+ }
+ return true;
+ }
+
+ private Object getValue(Map map, Object mkey) {
+ Set<Map.Entry> entries = map.entrySet();
+ for (Map.Entry entry : entries) {
+ if (entry.getKey().equals(mkey))
+ return entry.getValue();
+ }
+ return null;
+ }
+}