in openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java [327:494]
public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
if (field.getMappedBy() != null && !field.isBiMTo1JT())
return;
Map map = (Map) sm.fetchObject(field.getIndex());
ChangeTracker ct = null;
if (map instanceof Proxy) {
Proxy proxy = (Proxy) map;
if (Proxies.isOwner(proxy, sm, field.getIndex()))
ct = proxy.getChangeTracker();
}
// if no fine-grained change tracking then just delete and reinsert
if (ct == null || !ct.isTracking()) {
delete(sm, store, rm);
insert(sm, rm, map, store);
return;
}
ValueMapping key = field.getKeyMapping();
ValueMapping val = field.getElementMapping();
StoreContext ctx = store.getContext();
OpenJPAStateManager keysm, valsm;
// update the changes; note that we have to model changes as
// delete-then-insert if we have a foreign key action, because
// secondary row updates aren't part of the constraint graph
Collection change = ct.getChanged();
boolean canChange = val.getForeignKey().isLogical();
Object mkey;
if (canChange && !change.isEmpty()) {
Row changeRow = null;
if (!field.isUni1ToMFK()) {
changeRow = rm.getSecondaryRow(field.getTable(),
Row.ACTION_UPDATE);
changeRow.whereForeignKey(field.getJoinForeignKey(), sm);
}
for (Object o : change) {
mkey = o;
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(mval, ctx);
key.whereForeignKey(changeRow, keysm);
if (field.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 = null;
if (!field.isUni1ToMFK()) {
delRow = rm.getSecondaryRow(field.getTable(),
Row.ACTION_DELETE);
delRow.whereForeignKey(field.getJoinForeignKey(), sm);
}
for (Object pc : rem) {
if (field.isUni1ToMFK()) {
updateSetNull(sm, rm, pc);
}
else {
keysm = RelationStrategies.getStateManager(pc, ctx);
key.whereForeignKey(delRow, keysm);
rm.flushSecondaryRow(delRow);
}
}
if (!canChange && !change.isEmpty()) {
for (Object pc : change) {
if (field.isUni1ToMFK()) {
updateSetNull(sm, rm, pc);
}
else {
keysm = RelationStrategies.getStateManager(pc, ctx);
key.whereForeignKey(delRow, keysm);
rm.flushSecondaryRow(delRow);
}
}
}
}
// insert the adds
Collection add = ct.getAdded();
if (!add.isEmpty() || (!canChange && !change.isEmpty())) {
Row addRow = null;
if (!field.isUni1ToMFK()) {
addRow = rm.getSecondaryRow(field.getTable(),
Row.ACTION_INSERT);
addRow.setForeignKey(field.getJoinForeignKey(),
field.getJoinColumnIO(), sm);
}
for (Object value : add) {
mkey = value;
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(mval, ctx);
if (field.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 (Object o : change) {
mkey = o;
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(mval, ctx);
if (field.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);
}
}
}
}
}