OPENJPA-1253: refactoring the checking of non-default mapping to AbstractFieldStrategy

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@819822 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Fay Wang 2009-09-29 03:31:34 +00:00
parent 7d6ccb108c
commit c8d1003612
3 changed files with 139 additions and 115 deletions

View File

@ -20,10 +20,14 @@ package org.apache.openjpa.jdbc.meta.strats;
import java.sql.SQLException; import java.sql.SQLException;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration; import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore; import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.FieldMapping; import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.FieldMappingInfo;
import org.apache.openjpa.jdbc.meta.FieldStrategy; import org.apache.openjpa.jdbc.meta.FieldStrategy;
import org.apache.openjpa.jdbc.schema.ForeignKey;
import org.apache.openjpa.jdbc.sql.Joins; import org.apache.openjpa.jdbc.sql.Joins;
import org.apache.openjpa.jdbc.sql.Result; import org.apache.openjpa.jdbc.sql.Result;
import org.apache.openjpa.jdbc.sql.RowManager; import org.apache.openjpa.jdbc.sql.RowManager;
@ -32,6 +36,8 @@ import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.jdbc.sql.SelectExecutor; import org.apache.openjpa.jdbc.sql.SelectExecutor;
import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.MetaDataException; import org.apache.openjpa.util.MetaDataException;
/** /**
@ -46,6 +52,13 @@ public abstract class AbstractFieldStrategy
private static final Localizer _loc = Localizer.forPackage private static final Localizer _loc = Localizer.forPackage
(AbstractFieldStrategy.class); (AbstractFieldStrategy.class);
private Boolean _isNonDefaultMappingAllowed = null;
private Boolean _isBi1ToMJT = null;
private Boolean _isUni1ToMFK = null;
private Integer _bi1ToMJT = null; //index of the field
private ForeignKey _bi_1ToM_JoinFK = null;
private ForeignKey _bi_1ToM_ElemFK = null;
/** /**
* The owning field mapping. * The owning field mapping.
*/ */
@ -181,4 +194,107 @@ public abstract class AbstractFieldStrategy
Object prevValue) Object prevValue)
throws SQLException { throws SQLException {
} }
private void isNonDefaultMapping() {
FieldMapping mapped = field.getMappedByMapping();
_isBi1ToMJT = false;
_isUni1ToMFK = false;
if (isNonDefaultMappingAllowed()) {
if (field.getAssociationType() == FieldMetaData.ONE_TO_MANY ) {
if (mapped == null) {
if (hasJoinTable())
return;
else if (hasJoinColumn()) {
_isUni1ToMFK = true;
return;
}
} else {
if (hasJoinTable()) {
_isBi1ToMJT = true;
return;
} else if (hasJoinColumn()){
return;
}
}
}
}
}
private boolean hasJoinColumn() {
boolean hasJoinColumn = (field.getValueInfo().getColumns().size() > 0 ? true : false);
return hasJoinColumn;
}
private boolean hasJoinTable() {
boolean hasJoinTable = (field.getMappingInfo().getTableName() != null ? true : false);
return hasJoinTable;
}
public boolean isBi1ToMJT() {
if (_isBi1ToMJT == null)
isNonDefaultMapping();
return _isBi1ToMJT;
}
public boolean isUni1ToMFK() {
if (_isUni1ToMFK == null)
isNonDefaultMapping();
return _isUni1ToMFK;
}
protected boolean isNonDefaultMappingAllowed() {
if (_isNonDefaultMappingAllowed == null) {
OpenJPAConfiguration conf = field.getRepository().getConfiguration();
_isNonDefaultMappingAllowed = field.getRepository().
getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(conf);
}
return _isNonDefaultMappingAllowed;
}
protected void getBiOneToManyInfo() {
_bi1ToMJT = -1;
if (!isNonDefaultMappingAllowed())
return;
ClassMapping inverse = field.getValueMapping().getTypeMapping();
FieldMapping[] fmds = inverse.getFieldMappings();
for (int i = 0; i < fmds.length; i++) {
if (field == fmds[i].getMappedByMapping()) {
int typeCode = fmds[i].getDeclaredTypeCode();
if (typeCode == JavaTypes.ARRAY ||
typeCode == JavaTypes.COLLECTION ||
typeCode == JavaTypes.MAP) {
// this is a bi-directional oneToMany relation with
// @JoinTable annotation ==> join table strategy
// ==> should not mapped in the owner's table
FieldMappingInfo info = fmds[i].getMappingInfo();
if (info.getTableName() != null)
_bi1ToMJT = i;
_bi_1ToM_ElemFK = fmds[i].getElementMapping().getForeignKey();
_bi_1ToM_JoinFK = fmds[i].getJoinForeignKey();
}
break;
}
}
}
protected int getFieldIndexBi1ToMJT() {
if (_bi1ToMJT == null) {
getBiOneToManyInfo();
}
return _bi1ToMJT;
}
protected ForeignKey getBi1ToMElemFK() {
if (_bi1ToMJT == null) {
getBiOneToManyInfo();
}
return _bi_1ToM_ElemFK;
}
protected ForeignKey getBi1ToMJoinFK() {
if (_bi1ToMJT == null) {
getBiOneToManyInfo();
}
return _bi_1ToM_JoinFK;
}
} }

View File

@ -66,51 +66,10 @@ public abstract class MapTableFieldStrategy
private static final Localizer _loc = Localizer.forPackage private static final Localizer _loc = Localizer.forPackage
(MapTableFieldStrategy.class); (MapTableFieldStrategy.class);
private Boolean _isNonDefaultMappingAllowed = null;
private Boolean _isBi1ToMJT = null;
private Boolean _isUni1ToMFK = null;
public FieldMapping getFieldMapping() { public FieldMapping getFieldMapping() {
return field; return field;
} }
private void isNonDefaultMapping() {
FieldMapping mapped = field.getMappedByMapping();
if (isNonDefaultMappingAllowed() &&
field.getAssociationType() == FieldMetaData.ONE_TO_MANY &&
hasJoinColumnOrJoinTable()) {
if (mapped != null) {
_isBi1ToMJT = true;
_isUni1ToMFK = false;
} else {
_isBi1ToMJT = false;
_isUni1ToMFK = true;
}
} else {
_isBi1ToMJT = false;
_isUni1ToMFK = false;
}
}
private boolean hasJoinColumnOrJoinTable() {
boolean hasJoinColumn = (field.getValueInfo().getColumns().size() > 0 ? true : false);
boolean hasJoinTable = (field.getMappingInfo().getTableName() != null ? true : false);
return hasJoinColumn || hasJoinTable;
}
public boolean isBi1ToMJT() {
if (_isBi1ToMJT == null)
isNonDefaultMapping();
return _isBi1ToMJT;
}
public boolean isUni1ToMFK() {
if (_isUni1ToMFK == null)
isNonDefaultMapping();
return _isUni1ToMFK;
}
public ClassMapping[] getIndependentKeyMappings(boolean traverse) { public ClassMapping[] getIndependentKeyMappings(boolean traverse) {
return (traverse) ? field.getKeyMapping().getIndependentTypeMappings() return (traverse) ? field.getKeyMapping().getIndependentTypeMappings()
: ClassMapping.EMPTY_MAPPINGS; : ClassMapping.EMPTY_MAPPINGS;
@ -161,15 +120,6 @@ public abstract class MapTableFieldStrategy
field.getValueInfo().assertNoSchemaComponents(field, !adapt); field.getValueInfo().assertNoSchemaComponents(field, !adapt);
} }
protected boolean isNonDefaultMappingAllowed() {
if (_isNonDefaultMappingAllowed == null) {
OpenJPAConfiguration conf = field.getRepository().getConfiguration();
_isNonDefaultMappingAllowed = field.getRepository().
getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(conf);
}
return _isNonDefaultMappingAllowed;
}
public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm) public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException { throws SQLException {
Row row = rm.getAllRows(field.getTable(), Row.ACTION_DELETE); Row row = rm.getAllRows(field.getTable(), Row.ACTION_DELETE);

View File

@ -83,9 +83,6 @@ public class RelationFieldStrategy
(RelationFieldStrategy.class); (RelationFieldStrategy.class);
private Boolean _fkOid = null; private Boolean _fkOid = null;
private int _biOneToManyJoinTable = -1;
private ForeignKey _biOneToManyJoinFK = null;
private ForeignKey _biOneToManyElemFK = null;
public void map(boolean adapt) { public void map(boolean adapt) {
if (field.getTypeCode() != JavaTypes.PC || field.isEmbeddedPC()) if (field.getTypeCode() != JavaTypes.PC || field.isEmbeddedPC())
@ -139,10 +136,6 @@ public class RelationFieldStrategy
field.setUseClassCriteria(criteria); field.setUseClassCriteria(criteria);
return; return;
} else { // this could be the owner in a bi-directional relation } else { // this could be the owner in a bi-directional relation
OpenJPAConfiguration conf = field.getRepository().getConfiguration();
boolean isNonDefaultMappingAllowed = field.getRepository().
getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(conf);
if (isNonDefaultMappingAllowed)
getBiOneToManyInfo(); getBiOneToManyInfo();
} }
@ -168,7 +161,7 @@ public class RelationFieldStrategy
if (field.getMappedByIdValue() != null) if (field.getMappedByIdValue() != null)
setMappedByIdColumns(); setMappedByIdColumns();
if (_biOneToManyJoinTable == -1) { if (getFieldIndexBi1ToMJT() == -1) {
ForeignKey fk = vinfo.getTypeJoin(field, field.getName(), true, ForeignKey fk = vinfo.getTypeJoin(field, field.getName(), true,
adapt); adapt);
field.setForeignKey(fk); field.setForeignKey(fk);
@ -279,7 +272,7 @@ public class RelationFieldStrategy
updateInverse(sm, rel, store, rm); updateInverse(sm, rel, store, rm);
else { else {
Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT); Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
if (row != null && _biOneToManyJoinTable == -1) { if (row != null && getFieldIndexBi1ToMJT() == -1) {
field.setForeignKey(row, rel); field.setForeignKey(row, rel);
// this is for bi-directional maps, the key and value of the // this is for bi-directional maps, the key and value of the
// map are stored in the table of the mapped-by entity // map are stored in the table of the mapped-by entity
@ -346,6 +339,12 @@ public class RelationFieldStrategy
if (mapObj.get(key) == value) if (mapObj.get(key) == value)
return key; return key;
} }
Set<Map.Entry> entries = mapObj.entrySet();
for (Map.Entry entry : entries) {
if (entry.getValue() == value)
return entry.getKey();
}
return null; return null;
} }
@ -365,32 +364,28 @@ public class RelationFieldStrategy
field.isBidirectionalJoinTableMappingNonOwner()) ? field.isBidirectionalJoinTableMappingNonOwner()) ?
Row.ACTION_DELETE : Row.ACTION_UPDATE; Row.ACTION_DELETE : Row.ACTION_UPDATE;
Row row = field.getRow(sm, store, rm, action); Row row = field.getRow(sm, store, rm, action);
if (row != null && _biOneToManyJoinTable == -1) { if (row != null && getFieldIndexBi1ToMJT() == -1) {
field.setForeignKey(row, rel); field.setForeignKey(row, rel);
// this is for bi-directional maps, the key and value of the // this is for bi-directional maps, the key and value of the
// map are stored in the table of the mapped-by entity // map are stored in the table of the mapped-by entity
setMapKey(sm, rel, store, row); setMapKey(sm, rel, store, row);
} }
if (_biOneToManyJoinTable != -1) { // also need to update the join table if (getFieldIndexBi1ToMJT() != -1) { // also need to update the join table
PersistenceCapable invPC = (PersistenceCapable)sm.fetchObject(_biOneToManyJoinTable); PersistenceCapable invPC = (PersistenceCapable)sm.fetchObject(getFieldIndexBi1ToMJT());
Row secondaryRow = null; Row secondaryRow = null;
if (invPC != null) { if (invPC != null) {
secondaryRow = rm.getSecondaryRow(_biOneToManyJoinFK.getTable(), secondaryRow = rm.getSecondaryRow(getBi1ToMJoinFK().getTable(),
Row.ACTION_INSERT); Row.ACTION_INSERT);
secondaryRow.setForeignKey(_biOneToManyElemFK, null, sm); secondaryRow.setForeignKey(getBi1ToMElemFK(), null, sm);
secondaryRow.setForeignKey(_biOneToManyJoinFK, null, secondaryRow.setForeignKey(getBi1ToMJoinFK(), null,
RelationStrategies.getStateManager(invPC, RelationStrategies.getStateManager(invPC,
store.getContext())); store.getContext()));
} else {
secondaryRow = rm.getSecondaryRow(_biOneToManyJoinFK.getTable(),
Row.ACTION_DELETE);
secondaryRow.setForeignKey(_biOneToManyElemFK, null, sm);
}
rm.flushSecondaryRow(secondaryRow); rm.flushSecondaryRow(secondaryRow);
} }
} }
} }
}
public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm) public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException { throws SQLException {
@ -561,7 +556,7 @@ public class RelationFieldStrategy
*/ */
private void selectEagerParallel(Select sel, ClassMapping cls, private void selectEagerParallel(Select sel, ClassMapping cls,
JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) { JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
if (_biOneToManyJoinTable != -1) if (getFieldIndexBi1ToMJT() != -1)
return; return;
sel.selectPrimaryKey(field.getDefiningMapping()); sel.selectPrimaryKey(field.getDefiningMapping());
// set a variable name that does not conflict with any in the query; // set a variable name that does not conflict with any in the query;
@ -576,7 +571,7 @@ public class RelationFieldStrategy
public void selectEagerJoin(Select sel, OpenJPAStateManager sm, public void selectEagerJoin(Select sel, OpenJPAStateManager sm,
JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) { JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
if (_biOneToManyJoinTable != -1) if (getFieldIndexBi1ToMJT() != -1)
return; return;
// limit the eager mode to single on recursive eager fetching b/c // limit the eager mode to single on recursive eager fetching b/c
@ -681,7 +676,7 @@ public class RelationFieldStrategy
public void loadEagerJoin(OpenJPAStateManager sm, JDBCStore store, public void loadEagerJoin(OpenJPAStateManager sm, JDBCStore store,
JDBCFetchConfiguration fetch, Result res) JDBCFetchConfiguration fetch, Result res)
throws SQLException { throws SQLException {
if (_biOneToManyJoinTable != -1) if (getFieldIndexBi1ToMJT() != -1)
return; return;
ClassMapping cls = field.getIndependentTypeMappings()[0]; ClassMapping cls = field.getIndependentTypeMappings()[0];
@ -730,7 +725,7 @@ public class RelationFieldStrategy
// get the related object's oid // get the related object's oid
ClassMapping relMapping = field.getTypeMapping(); ClassMapping relMapping = field.getTypeMapping();
Object oid = null; Object oid = null;
if (relMapping.isMapped() && _biOneToManyJoinTable == -1) { if (relMapping.isMapped() && getFieldIndexBi1ToMJT() == -1) {
oid = relMapping.getObjectId(store, res, field.getForeignKey(), oid = relMapping.getObjectId(store, res, field.getForeignKey(),
field.getPolymorphic() != ValueMapping.POLY_FALSE, null); field.getPolymorphic() != ValueMapping.POLY_FALSE, null);
} else { } else {
@ -796,16 +791,16 @@ public class RelationFieldStrategy
sel.whereForeignKey(field.getForeignKey(rels[idx]), sel.whereForeignKey(field.getForeignKey(rels[idx]),
sm.getObjectId(), field.getDefiningMapping(), store); sm.getObjectId(), field.getDefiningMapping(), store);
else { else {
if (_biOneToManyJoinTable == -1) { if (getFieldIndexBi1ToMJT() == -1) {
resJoins[idx] = sel.newJoins().joinRelation(field.getName(), resJoins[idx] = sel.newJoins().joinRelation(field.getName(),
field.getForeignKey(rels[idx]), rels[idx], field.getForeignKey(rels[idx]), rels[idx],
field.getSelectSubclasses(), false, false); field.getSelectSubclasses(), false, false);
field.wherePrimaryKey(sel, sm, store); field.wherePrimaryKey(sel, sm, store);
} else { } else {
resJoins[idx] = sel.newJoins().joinRelation(null, resJoins[idx] = sel.newJoins().joinRelation(null,
getBiOneToManyJoinFK(), rels[idx], getBi1ToMJoinFK(), rels[idx],
field.getSelectSubclasses(), false, false); field.getSelectSubclasses(), false, false);
sel.whereForeignKey(getBiOneToManyElemFK(), sm.getObjectId(), sel.whereForeignKey(getBi1ToMElemFK(), sm.getObjectId(),
field.getDefiningMapping(), store); field.getDefiningMapping(), store);
} }
} }
@ -826,43 +821,6 @@ public class RelationFieldStrategy
} }
} }
private ForeignKey getBiOneToManyJoinFK() {
if (_biOneToManyJoinFK == null) {
getBiOneToManyInfo();
}
return _biOneToManyJoinFK;
}
private ForeignKey getBiOneToManyElemFK() {
if (_biOneToManyElemFK == null) {
getBiOneToManyInfo();
}
return _biOneToManyElemFK;
}
private void getBiOneToManyInfo() {
ClassMapping inverse = field.getValueMapping().getTypeMapping();
FieldMapping[] fmds = inverse.getFieldMappings();
for (int i = 0; i < fmds.length; i++) {
if (field == fmds[i].getMappedByMapping()) {
int typeCode = fmds[i].getDeclaredTypeCode();
if (typeCode == JavaTypes.ARRAY ||
typeCode == JavaTypes.COLLECTION ||
typeCode == JavaTypes.MAP) {
// this is a bi-directional oneToMany relation with
// @JoinTable annotation ==> join table strategy
// ==> should not mapped in the owner's table
FieldMappingInfo info = fmds[i].getMappingInfo();
if (info.getTableName() != null)
_biOneToManyJoinTable = i;
_biOneToManyElemFK = fmds[i].getElementMapping().getForeignKey();
_biOneToManyJoinFK = fmds[i].getJoinForeignKey();
}
break;
}
}
}
public Object toDataStoreValue(Object val, JDBCStore store) { public Object toDataStoreValue(Object val, JDBCStore store) {
return RelationStrategies.toDataStoreValue(field, val, store); return RelationStrategies.toDataStoreValue(field, val, store);
} }