OPENJPA:2099: Cacheing select construct with class/field strategy. Adding configuration

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1232415 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2012-01-17 14:04:07 +00:00
parent 5bb79b9309
commit 1a50b5fe76
20 changed files with 598 additions and 423 deletions

View File

@ -629,4 +629,24 @@ public interface JDBCConfiguration
*/
public void setIdentifierUtil(DBIdentifierUtil util);
/**
* Affirms if select statements are aggressively cached.
* An aggressive select cache assumes that {@link FetchConfiguration fetch plan}
* does not change between execution.
*
* @return false by default.
*
* @since 2.2.0
*/
public boolean getSelectCacheEnabled();
/**
* Sets if select statements are aggressively cached.
* An aggressive select cache assumes that {@link FetchConfiguration fetch plan}
* does not change between execution.
*
* @since 2.2.0
*/
public void setSelectCacheEnabled(boolean enable);
}

View File

@ -43,6 +43,8 @@ import org.apache.openjpa.jdbc.sql.MaxDBDictionary;
import org.apache.openjpa.jdbc.sql.SQLFactory;
import org.apache.openjpa.kernel.BrokerImpl;
import org.apache.openjpa.kernel.StoreContext;
import org.apache.openjpa.lib.conf.BooleanValue;
import org.apache.openjpa.lib.conf.ImmutableBooleanValue;
import org.apache.openjpa.lib.conf.IntValue;
import org.apache.openjpa.lib.conf.ObjectValue;
import org.apache.openjpa.lib.conf.PluginValue;
@ -87,6 +89,7 @@ public class JDBCConfigurationImpl
public PluginValue driverDataSourcePlugin;
public MappingFactoryValue mappingFactoryPlugin;
public ObjectValue identifierUtilPlugin;
public ImmutableBooleanValue cacheSelect;
// used internally
private String firstUser = null;
@ -350,6 +353,9 @@ public class JDBCConfigurationImpl
identifierUtilPlugin.setString(aliases[0]);
identifierUtilPlugin.setInstantiatingGetter("getIdentifierUtilInstance");
cacheSelect = new ImmutableBooleanValue("jdbc.CachesSelect");
addValue(cacheSelect);
cacheSelect.setDefault("false");
// this static initializer is to get past a weird
// ClassCircularityError that happens only under IBM's
@ -997,4 +1003,12 @@ public class JDBCConfigurationImpl
identifierUtilPlugin.set(util);
}
public boolean getSelectCacheEnabled() {
return cacheSelect.get();
}
public void setSelectCacheEnabled(boolean enable) {
cacheSelect.set(enable);
}
}

View File

@ -260,9 +260,9 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
private boolean exists(ClassMapping mapping, Object oid, Object context) {
// add where conditions on base class to avoid joins if subclass
// doesn't use oid as identifier
Select sel = _sql.newSelect();
while (mapping.getJoinablePCSuperclassMapping() != null)
mapping = mapping.getJoinablePCSuperclassMapping();
Select sel = mapping.getSelect();
sel.wherePrimaryKey(oid, mapping, this);
if (_log.isTraceEnabled()) {
@ -301,8 +301,7 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
FetchConfiguration fetch, Object context) {
ConnectionInfo info = (ConnectionInfo) context;
try {
return initializeState(sm, state, (JDBCFetchConfiguration) fetch,
info);
return initializeState(sm, state, (JDBCFetchConfiguration) fetch, info);
} catch (ClassNotFoundException cnfe) {
throw new UserException(cnfe);
} catch (SQLException se) {
@ -332,27 +331,24 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
Boolean custom = customLoad(sm, mapping, state, fetch);
if (custom != null)
return custom.booleanValue();
res = getInitializeStateResult(sm, mapping, fetch,
Select.SUBS_EXACT);
res = getInitializeStateResult(sm, mapping, fetch, Select.SUBS_EXACT);
if (res == null && !selectPrimaryKey(sm, mapping, fetch))
return false;
if (isEmptyResult(res))
return false;
} else {
ClassMapping[] mappings = mapping.
getIndependentAssignableMappings();
ClassMapping[] mappings = mapping.getIndependentAssignableMappings();
if (mappings.length == 1) {
mapping = mappings[0];
Boolean custom = customLoad(sm, mapping, state, fetch);
if (custom != null)
return custom.booleanValue();
res = getInitializeStateResult(sm, mapping, fetch,
Select.SUBS_ANY_JOINABLE);
res = getInitializeStateResult(sm, mapping, fetch, Select.SUBS_ANY_JOINABLE);
if (res == null && !selectPrimaryKey(sm, mapping, fetch))
return false;
} else
res = getInitializeStateUnionResult(sm, mapping, mappings,
fetch);
} else {
res = getInitializeStateUnionResult(sm, mapping, mappings, fetch);
}
if (isEmptyResult(res))
return false;
}
@ -365,8 +361,7 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
mapping = res.getBaseMapping();
res.startDataRequest(mapping.getDiscriminator());
try {
type = mapping.getDiscriminator().getClass(this, mapping,
res);
type = mapping.getDiscriminator().getClass(this, mapping, res);
} finally {
res.endDataRequest();
}
@ -378,19 +373,15 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
sm.initialize(type, state);
if (info != null && info.result != null) {
FieldMapping mappedByFieldMapping = info.result.
getMappedByFieldMapping();
FieldMapping mappedByFieldMapping = info.result.getMappedByFieldMapping();
Object mappedByObject = info.result.getMappedByValue();
if (mappedByFieldMapping != null && mappedByObject != null)
if (mappedByObject instanceof OpenJPAId &&
mapping.getExtraFieldDataIndex(mappedByFieldMapping.getIndex()) != -1) {
// The inverse relation can not be set since
// we are eagerly loading this sm for
// a sm owner that is still in the process of
// initializing itself.
// The inverse relation can not be set since we are eagerly loading this sm for
// an owner that is still in the process of initializing itself.
// Remember owner oid by setIntermediate().
// The inverse relation is set later by
// setInverseRelation() when the sm owner is fully
// The inverse relation is set later by setInverseRelation() when the owner is fully
// initialized.
int index = mappedByFieldMapping.getIndex();
if (sm.getLoaded().get(index)) {
@ -535,7 +526,7 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
FinderQueryImpl fq = getFinder(mapping, fetch);
if (fq != null)
return fq.execute(sm, this, fetch);
Select sel = _sql.newSelect();
Select sel = mapping.getSelect();
if (!select(sel, mapping, subs, sm, null, fetch,
JDBCFetchConfiguration.EAGER_JOIN, true, false))
return null;
@ -563,7 +554,7 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
final int eager = Math.min(fetch.getEagerFetchMode(),
JDBCFetchConfiguration.EAGER_JOIN);
Union union = _sql.newUnion(mappings.length);
Union union = mapping.getUnion(mappings.length);
union.setExpectedResultCount(1, false);
if (fetch.getSubclassFetchMode(mapping) != EagerFetchModes.EAGER_JOIN)
union.abortUnion();
@ -592,7 +583,7 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
while (base.getJoinablePCSuperclassMapping() != null)
base = base.getJoinablePCSuperclassMapping();
Select sel = _sql.newSelect();
Select sel = mapping.getSelect();
sel.select(base.getPrimaryKeyColumns());
sel.wherePrimaryKey(sm.getObjectId(), base, this);
if (_log.isTraceEnabled()) {
@ -645,7 +636,7 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
//### use it... would it be worth it to have a small shell select
//### object that only creates a real select when actually used?
Select sel = _sql.newSelect();
Select sel = mapping.getSelect();
if (select(sel, mapping, Select.SUBS_EXACT, sm, fields, jfetch,
EagerFetchModes.EAGER_JOIN, true, false)) {
sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
@ -818,7 +809,7 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
if (rops[i] != null)
continue;
Select sel = _sql.newSelect();
Select sel = mapping.getSelect();
sel.setLRS(true);
if (_log.isTraceEnabled()) {
_log.trace("executeExtent: "+mappings[i].getDescribedType());
@ -839,13 +830,12 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
}
// perform a union on all independent classes
Union union = _sql.newUnion(mappings.length);
Union union = mapping.getUnion(mappings.length);
union.setLRS(true);
final BitSet[] paged = new BitSet[mappings.length];
union.select(new Union.Selector() {
public void select(Select sel, int idx) {
paged[idx] = selectExtent(sel, mappings[idx], jfetch,
subclasses);
paged[idx] = selectExtent(sel, mappings[idx], jfetch, subclasses);
}
});
@ -1124,6 +1114,8 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
public boolean select(Select sel, ClassMapping mapping, int subs,
OpenJPAStateManager sm, BitSet fields, JDBCFetchConfiguration fetch,
int eager, boolean ident, boolean outer) {
if (sel.isReadOnly())
return true;
// add class conditions so that they're cloned for any batched selects
boolean joinedSupers = false;
if(needClassCondition(mapping, subs, sm)) {
@ -1134,8 +1126,7 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
// and cannot be reused during the actual eager select process,
// preventing infinite recursion
eager = Math.min(eager, fetch.getEagerFetchMode());
FieldMapping eagerToMany = createEagerSelects(sel, mapping, sm, fields,
fetch, eager);
FieldMapping eagerToMany = createEagerSelects(sel, mapping, sm, fields, fetch, eager);
// select all base class mappings; do this after batching so that
// the joins needed by these selects don't get in the WHERE clause
@ -1145,10 +1136,9 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
// select eager to-many relations last because during load they
// advance the result set and could exhaust it, so no other mappings
// can load afterwords
// can load afterwards
if (eagerToMany != null)
eagerToMany.selectEagerJoin(sel, sm, this,
fetch.traverseJDBC(eagerToMany), eager);
eagerToMany.selectEagerJoin(sel, sm, this, fetch.traverseJDBC(eagerToMany), eager);
// optionally select subclass mappings
if (subs == Select.SUBS_JOINABLE || subs == Select.SUBS_ANY_JOINABLE)
@ -1164,8 +1154,7 @@ public class JDBCStoreManager implements StoreManager, JDBCStore {
return mapping.getDiscriminator().addClassConditions(sel, subs == Select.SUBS_JOINABLE, joins);
}
private boolean needClassCondition(ClassMapping mapping, int subs,
OpenJPAStateManager sm) {
private boolean needClassCondition(ClassMapping mapping, int subs, OpenJPAStateManager sm) {
boolean retVal = false;
if(sm == null || sm.getPCState() == PCState.TRANSIENT) {
if(subs == Select.SUBS_JOINABLE || subs == Select.SUBS_NONE) {

View File

@ -31,6 +31,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.enhance.Reflection;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
@ -44,6 +45,8 @@ import org.apache.openjpa.jdbc.sql.Joins;
import org.apache.openjpa.jdbc.sql.Result;
import org.apache.openjpa.jdbc.sql.RowManager;
import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.jdbc.sql.SelectExecutor;
import org.apache.openjpa.jdbc.sql.Union;
import org.apache.openjpa.kernel.FetchConfiguration;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.PCState;
@ -60,17 +63,22 @@ import org.apache.openjpa.util.OpenJPAId;
/**
* Specialization of metadata for relational databases.
* <br>
* The mapping may reuse the same {@link SelectExecutor select} if the
* {@link JDBCConfiguration#getSelectCacheEnabled() configuration option}
* instructs to do so.
*
* @author Abe White
* @author Pinaki Poddar (select caching)
*/
@SuppressWarnings("serial")
public class ClassMapping
extends ClassMetaData
implements ClassStrategy {
public static final ClassMapping[] EMPTY_MAPPINGS = new ClassMapping[0];
private static final Localizer _loc = Localizer.forPackage
(ClassMapping.class);
private static final Localizer _loc = Localizer.forPackage(ClassMapping.class);
private final ClassMappingInfo _info;
private final Discriminator _discrim;
@ -89,6 +97,9 @@ public class ClassMapping
// maps columns to joinables
private final Map _joinables = new ConcurrentHashMap();
private Select _select;
private Union _union;
/**
* Constructor. Supply described type and owning repository.
*/
@ -1109,4 +1120,48 @@ public class ClassMapping
return true;
return false;
}
/**
* Gets the {@link Select select} used for selecting instances of this mapping.
* If {@link JDBCConfiguration#getSelectCacheEnabled() aggressive caching} of
* select statements is enabled, then a select is generated for the first call,
* cached in this mapping and subsequently returned. A cached select becomes
* {@link Select#isReadOnly() immutable} i.e. no structural modification is
* allowed <em>after</em> its corresponding SQL has been executed on the database.
*
* @return a new or cached select to select instances of this mapping.
*/
public Select getSelect() {
Select result = _select;
if (result == null) {
JDBCConfiguration conf = (JDBCConfiguration)getMappingRepository().getConfiguration();
result = conf.getSQLFactoryInstance().newSelect();
if (conf.getSelectCacheEnabled()) {
_select = result;
}
}
return result;
}
/**
* Gets the {@link Union union} used for selecting instances of this mapping.
* If {@link JDBCConfiguration#getSelectCacheEnabled() aggressive caching} of
* union statements is enabled, then a union is generated for the first call,
* cached in this mapping and subsequently returned. A cached union becomes
* {@link Select#isReadOnly() immutable} i.e. no structural modification is
* allowed <em>after</em> its corresponding SQL has been executed on the database.
*
* @return a new or cached union to select instances of this mapping.
*/
public Union getUnion(int selects) {
Union result = _union;
if (result == null) {
JDBCConfiguration conf = (JDBCConfiguration)getMappingRepository().getConfiguration();
result = conf.getSQLFactoryInstance().newUnion(selects);
if (conf.getSelectCacheEnabled()) {
_union = result;
}
}
return result;
}
}

View File

@ -81,19 +81,19 @@ public class FieldMapping
private boolean _outer = false;
private int _fetchMode = Integer.MAX_VALUE;
private Unique[] _joinTableUniques; // Unique constraints on JoinTable
private Boolean _bidirectionalJoinTableOwner = null;
private Boolean _bidirectionalJoinTableNonOwner = null;
private Boolean _bidirectionalJoinTableOwner;
private Boolean _bidirectionalJoinTableNonOwner;
private Boolean _bi_MTo1_JT = null;
private Boolean _uni_1ToM_FK = null;
private Boolean _uni_MTo1_JT = null;
private Boolean _uni_1To1_JT = null;
private Boolean _bi_1To1_JT = null;
private Boolean _bidirectionalManyToOneJoinTable;
private Boolean _unidirectionalOneToManyForeignKey;
private Boolean _unidirectionalManyToOneJoinTable;
private Boolean _unidirectionalOneToOneJoinTable;
private Boolean _bidirectionalOneToOneJoinTable;
private FieldMapping _bi_1ToM_JT_Field = null;
private FieldMapping _bi_MTo1_JT_Field = null;
private ForeignKey _bi_1ToM_Join_FK = null;
private ForeignKey _bi_1ToM_Elem_FK = null;
private FieldMapping _bidirectionalOneToManyJoinTableField;
private FieldMapping _bidirectionalManyToOneJoinTableField;
private ForeignKey _bidirectionalOneToManyJoinForeignKey;
private ForeignKey _bidirectionalOneToManyElementForeignKey;
private boolean _hasMapsIdCols = false;
@ -1271,85 +1271,90 @@ public class FieldMapping
return _bidirectionalJoinTableNonOwner.booleanValue();
}
public boolean isBiMTo1JT() {
if (_bi_MTo1_JT == null) {
_bi_MTo1_JT = getMappingRepository().isBiMTo1JT(this);
public boolean isBidirectionalManyToOneJoinTable() {
if (_bidirectionalManyToOneJoinTable == null) {
_bidirectionalManyToOneJoinTable = getMappingRepository().isBidirectionalManyToOneJoinTable(this);
}
return _bi_MTo1_JT;
return _bidirectionalManyToOneJoinTable;
}
public boolean isUni1ToMFK() {
if (_uni_1ToM_FK == null)
_uni_1ToM_FK = getMappingRepository().isUni1ToMFK(this);
return _uni_1ToM_FK;
public boolean isUnidirectionalOneToManyForeignKey() {
if (_unidirectionalOneToManyForeignKey == null)
_unidirectionalOneToManyForeignKey = getMappingRepository().isUnidirectionalOneToManyForeignKey(this);
return _unidirectionalOneToManyForeignKey;
}
public boolean isUniMTo1JT() {
if (_uni_MTo1_JT == null)
_uni_MTo1_JT = getMappingRepository().isUniMTo1JT(this);
return _uni_MTo1_JT;
public boolean isUnidirectionalManyToOneJoinTable() {
if (_unidirectionalManyToOneJoinTable == null)
_unidirectionalManyToOneJoinTable = getMappingRepository().isUnidirectionalManyToOneJoinTable(this);
return _unidirectionalManyToOneJoinTable;
}
public boolean isUni1To1JT() {
if (_uni_1To1_JT == null)
_uni_1To1_JT = getMappingRepository().isUni1To1JT(this);
return _uni_1To1_JT;
public boolean isUnidirectionalOneToOneJoinTable() {
if (_unidirectionalOneToOneJoinTable == null)
_unidirectionalOneToOneJoinTable = getMappingRepository().isUnidirectionalOneToOneJoinTable(this);
return _unidirectionalOneToOneJoinTable;
}
public boolean isBi1To1JT() {
if (_bi_1To1_JT == null)
_bi_1To1_JT = getMappingRepository().isBi1To1JT(this);
return _bi_1To1_JT;
public boolean isBidirectionalOneToOneJoinTable() {
if (_bidirectionalOneToOneJoinTable == null)
_bidirectionalOneToOneJoinTable = getMappingRepository().isBidirectionalOneToOneJoinTable(this);
return _bidirectionalOneToOneJoinTable;
}
public FieldMapping getBi_1ToM_JTField() {
if (_bi_1ToM_JT_Field == null) {
_bi_1ToM_JT_Field = getMappingRepository().getBi_1ToM_JoinTableField(this);
public FieldMapping getBidirectionalOneToManyJoinTableField() {
if (_bidirectionalOneToManyJoinTableField == null) {
_bidirectionalOneToManyJoinTableField =
getMappingRepository().getBidirectionalOneToManyJoinTableField(this);
}
return _bi_1ToM_JT_Field;
return _bidirectionalOneToManyJoinTableField;
}
public FieldMapping getBi_MTo1_JTField() {
if (_bi_MTo1_JT_Field == null) {
_bi_MTo1_JT_Field = getMappingRepository().getBi_MTo1_JoinTableField(this);
public FieldMapping getBidirectionalManyToOneJoinTableField() {
if (_bidirectionalManyToOneJoinTableField == null) {
_bidirectionalManyToOneJoinTableField =
getMappingRepository().getBidirectionalManyToOneJoinTableField(this);
}
return _bi_MTo1_JT_Field;
return _bidirectionalManyToOneJoinTableField;
}
public ForeignKey getBi1ToMJoinFK() {
if (_bi_1ToM_Join_FK == null) {
getBi_1ToM_JTField();
if (_bi_1ToM_JT_Field != null)
_bi_1ToM_Join_FK = _bi_1ToM_JT_Field.getJoinForeignKey();
public ForeignKey getBidirectionalOneToManyJoinForeignKey() {
if (_bidirectionalOneToManyJoinForeignKey == null) {
getBidirectionalOneToManyJoinTableField();
if (_bidirectionalOneToManyJoinTableField != null)
_bidirectionalOneToManyJoinForeignKey = _bidirectionalOneToManyJoinTableField.getJoinForeignKey();
}
return _bi_1ToM_Join_FK;
return _bidirectionalOneToManyJoinForeignKey;
}
public ForeignKey getBi1ToMElemFK() {
if (_bi_1ToM_Elem_FK == null) {
getBi_1ToM_JTField();
if (_bi_1ToM_JT_Field != null)
_bi_1ToM_Elem_FK = _bi_1ToM_JT_Field.getElementMapping().getForeignKey();
public ForeignKey getBidirectionalOneToManyElementForeignKey() {
if (_bidirectionalOneToManyElementForeignKey == null) {
getBidirectionalOneToManyJoinTableField();
if (_bidirectionalOneToManyJoinTableField != null)
_bidirectionalOneToManyElementForeignKey =
_bidirectionalOneToManyJoinTableField.getElementMapping().getForeignKey();
}
return _bi_1ToM_Elem_FK;
return _bidirectionalOneToManyElementForeignKey;
}
public void setBi1MJoinTableInfo() {
public void setBidirectionalOneToManyJoinTableInfo() {
if (getAssociationType() == FieldMetaData.ONE_TO_MANY) {
FieldMapping mapped = getBi_MTo1_JTField();
FieldMapping mapped = getBidirectionalManyToOneJoinTableField();
if (mapped != null) {
FieldMappingInfo info = getMappingInfo();
FieldMappingInfo mappedInfo = mapped.getMappingInfo();
info.setTableIdentifier(mappedInfo.getTableIdentifier());
info.setColumns(mapped.getElementMapping().getValueInfo().getColumns());
getElementMapping().getValueInfo().setColumns(
mappedInfo.getColumns());
getElementMapping().getValueInfo().setColumns(mappedInfo.getColumns());
}
}
}
public boolean isNonDefaultMappingUsingJoinTableStrategy() {
return isBi1To1JT() || isUni1To1JT() || isUniMTo1JT() || isBiMTo1JT();
return isBidirectionalOneToOneJoinTable()
|| isUnidirectionalOneToOneJoinTable()
|| isUnidirectionalManyToOneJoinTable()
|| isBidirectionalManyToOneJoinTable();
}
public void setMapsIdCols(boolean hasMapsIdCols) {

View File

@ -165,7 +165,7 @@ public class FieldMappingInfo
public ForeignKey getJoinForeignKey (final FieldMapping field, Table table,
boolean adapt) {
if (field.isUni1ToMFK()) {
if (field.isUnidirectionalOneToManyForeignKey()) {
List<Column> cols = field.getElementMapping().getValueInfo().getColumns();
return getJoin(field, table, adapt, cols);
}

View File

@ -105,15 +105,14 @@ import org.apache.openjpa.util.UserException;
*
* @author Abe White
*/
@SuppressWarnings("serial")
public class MappingRepository extends MetaDataRepository {
private static final Localizer _loc = Localizer.forPackage
(MappingRepository.class);
private static final Localizer _loc = Localizer.forPackage(MappingRepository.class);
private transient DBDictionary _dict = null;
private transient MappingDefaults _defaults = null;
// object->queryresultmapping
private Map<Object, QueryResultMapping> _results = new HashMap<Object, QueryResultMapping>();
private SchemaGroup _schema = null;
private StrategyInstaller _installer = null;
@ -260,12 +259,10 @@ public class MappingRepository extends MetaDataRepository {
public QueryResultMapping[] getQueryResultMappings() {
if (_locking) {
synchronized (this) {
Collection values = _results.values();
return (QueryResultMapping[]) values.toArray(new QueryResultMapping[values.size()]);
return _results.values().toArray(new QueryResultMapping[_results.size()]);
}
} else {
Collection values = _results.values();
return (QueryResultMapping[]) values.toArray(new QueryResultMapping[values.size()]);
return _results.values().toArray(new QueryResultMapping[_results.size()]);
}
}
@ -273,7 +270,7 @@ public class MappingRepository extends MetaDataRepository {
* Return the cached query result mapping with the given name, or null if
* none.
*/
public QueryResultMapping getCachedQueryResultMapping(Class cls, String name) {
public QueryResultMapping getCachedQueryResultMapping(Class<?> cls, String name) {
if (_locking) {
synchronized (this) {
return (QueryResultMapping) _results.get(getQueryResultKey(cls, name));
@ -286,7 +283,7 @@ public class MappingRepository extends MetaDataRepository {
/**
* Add a query result mapping.
*/
public QueryResultMapping addQueryResultMapping(Class cls, String name) {
public QueryResultMapping addQueryResultMapping(Class<?> cls, String name) {
if (_locking) {
synchronized (this) {
return addQueryResultMappingInternal(cls, name);
@ -296,7 +293,7 @@ public class MappingRepository extends MetaDataRepository {
}
}
private QueryResultMapping addQueryResultMappingInternal(Class cls, String name) {
private QueryResultMapping addQueryResultMappingInternal(Class<?> cls, String name) {
QueryResultMapping res = new QueryResultMapping(name, this);
res.setDefiningType(cls);
_results.put(getQueryResultKey(res), res);
@ -319,7 +316,7 @@ public class MappingRepository extends MetaDataRepository {
/**
* Remove a query result mapping.
*/
public boolean removeQueryResultMapping(Class cls, String name) {
public boolean removeQueryResultMapping(Class<?> cls, String name) {
if (_locking) {
synchronized (this) {
if (name == null)
@ -1008,8 +1005,7 @@ public class MappingRepository extends MetaDataRepository {
protected FieldStrategy handlerCollectionStrategy(FieldMapping field,
ValueHandler ehandler, boolean installHandlers) {
// TODO: JPA 2.0 should ignore this flag and not to serialize
if (getConfiguration().getCompatibilityInstance()
.getStoreMapCollectionInEntityAsBlob())
if (getConfiguration().getCompatibilityInstance().getStoreMapCollectionInEntityAsBlob())
return null;
if (installHandlers)
field.getElementMapping().setHandler(ehandler);
@ -1024,8 +1020,7 @@ public class MappingRepository extends MetaDataRepository {
ValueHandler khandler, ValueHandler vhandler, boolean krel,
boolean vrel, boolean installHandlers) {
// TODO: JPA 2.0 should ignore this flag and not to serialize
if (getConfiguration().getCompatibilityInstance()
.getStoreMapCollectionInEntityAsBlob())
if (getConfiguration().getCompatibilityInstance().getStoreMapCollectionInEntityAsBlob())
return null;
if (installHandlers) {
field.getKeyMapping().setHandler(khandler);
@ -1048,14 +1043,13 @@ public class MappingRepository extends MetaDataRepository {
FieldMapping mapped = field.getMappedByMapping();
if (mapped != null) {
//bi-/M-1/JoinTable ==> join table strategy
if (isBiMTo1JT(field))
if (isBidirectionalManyToOneJoinTable(field))
return false;
if (mapped.getTypeCode() == JavaTypes.PC || mapped.getTypeCode() == JavaTypes.PC_UNTYPED)
return true;
if (mapped.getElement().getTypeCode() == JavaTypes.PC)
return false;
throw new MetaDataException(_loc.get("bad-mapped-by", field,
mapped));
throw new MetaDataException(_loc.get("bad-mapped-by", field, mapped));
}
// without a mapped-by, we have to look for clues as to the mapping.
@ -1064,82 +1058,84 @@ public class MappingRepository extends MetaDataRepository {
// an association table
FieldMappingInfo info = field.getMappingInfo();
ValueMapping elem = field.getElementMapping();
boolean useInverseKeyMapping = DBIdentifier.isNull(info.getTableIdentifier()) && info.getColumns().isEmpty()
&& !elem.getValueInfo().getColumns().isEmpty();
boolean useInverseKeyMapping = DBIdentifier.isNull(info.getTableIdentifier())
&& info.getColumns().isEmpty()
&& !elem.getValueInfo().getColumns().isEmpty();
// JPA 2.0: non-default mapping: uni-/1-M/JoinColumn ==> foreign key strategy
if (isUni1ToMFK(field)) {
if (isUnidirectionalOneToManyForeignKey(field)) {
return true;
}
return useInverseKeyMapping;
}
public boolean isNonDefaultMappingAllowed() {
OpenJPAConfiguration conf = getConfiguration();
return getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(conf);
return getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(getConfiguration());
}
public boolean isUniMTo1JT(FieldMapping field) {
if (isNonDefaultMappingAllowed() &&
field.getAssociationType() == FieldMetaData.MANY_TO_ONE &&
hasJoinTable(field) &&
!isBidirectional(field)) {
public boolean isUnidirectionalManyToOneJoinTable(FieldMapping field) {
if (isNonDefaultMappingAllowed()
&& field.getAssociationType() == FieldMetaData.MANY_TO_ONE
&& hasJoinTable(field)
&& !isBidirectional(field)) {
field.getValueMapping().getValueInfo().setColumns(field.getElementMapping().getValueInfo().getColumns());
return true;
}
return false;
}
public boolean isUni1To1JT(FieldMapping field) {
if (isNonDefaultMappingAllowed() &&
field.getAssociationType() == FieldMetaData.ONE_TO_ONE &&
hasJoinTable(field) &&
!isBidirectional(field)) {
public boolean isUnidirectionalOneToOneJoinTable(FieldMapping field) {
if (isNonDefaultMappingAllowed()
&& field.getAssociationType() == FieldMetaData.ONE_TO_ONE
&& hasJoinTable(field)
&& !isBidirectional(field)) {
field.getValueMapping().getValueInfo().setColumns(field.getElementMapping().getValueInfo().getColumns());
return true;
}
return false;
}
public boolean isBi1To1JT(FieldMapping field) {
if (isNonDefaultMappingAllowed() &&
field.getAssociationType() == FieldMetaData.ONE_TO_ONE &&
hasJoinTable(field) &&
isBidirectional(field)) {
public boolean isBidirectionalOneToOneJoinTable(FieldMapping field) {
if (isNonDefaultMappingAllowed()
&& field.getAssociationType() == FieldMetaData.ONE_TO_ONE
&& hasJoinTable(field)
&& isBidirectional(field)) {
field.getValueMapping().getValueInfo().setColumns(field.getElementMapping().getValueInfo().getColumns());
return true;
}
return false;
}
public boolean isUni1ToMFK(FieldMapping field) {
if (isNonDefaultMappingAllowed() &&
field.getAssociationType() == FieldMetaData.ONE_TO_MANY &&
hasJoinColumn(field) &&
!isBidirectional(field)) {
public boolean isUnidirectionalOneToManyForeignKey(FieldMapping field) {
if (isNonDefaultMappingAllowed()
&& field.getAssociationType() == FieldMetaData.ONE_TO_MANY
&& hasJoinColumn(field)
&& !isBidirectional(field)) {
field.getElementMapping().getValueInfo().setColumns(field.getValueInfo().getColumns());
return true;
}
return false;
}
public boolean isBiMTo1JT(FieldMapping field) {
public boolean isBidirectionalManyToOneJoinTable(FieldMapping field) {
FieldMapping mapped = field.getMappedByMapping();
if (isNonDefaultMappingAllowed()) {
if (field.getAssociationType() == FieldMetaData.ONE_TO_MANY ) {
if (mapped != null && hasJoinTable(mapped))
return true;
} else if (field.getAssociationType() == FieldMetaData.MANY_TO_ONE) {
if (getBi_1ToM_JoinTableField(field) != null)
if (getBidirectionalOneToManyJoinTableField(field) != null)
return true;
}
}
return false;
}
// return the inverse field of bidirectional many to one
// relation using join table strategy
public FieldMapping getBi_1ToM_JoinTableField(FieldMapping field) {
/**
* Gets the inverse field of bidirectional many to one relation using join table strategy
* for the given field.
*/
public FieldMapping getBidirectionalOneToManyJoinTableField(FieldMapping field) {
if (isNonDefaultMappingAllowed()) {
if (field.getAssociationType() == FieldMetaData.ONE_TO_MANY) {
FieldMapping mappedBy = field.getMappedByMapping();
@ -1159,9 +1155,10 @@ public class MappingRepository extends MetaDataRepository {
return null;
}
// return the owning field of bidirectional one to many
// relation using join table strategy
public FieldMapping getBi_MTo1_JoinTableField(FieldMapping field) {
/**
* Gets the owning field of bidirectional one to many relation using join table strategy of the given field.
*/
public FieldMapping getBidirectionalManyToOneJoinTableField(FieldMapping field) {
if (isNonDefaultMappingAllowed()) {
if (field.getAssociationType() == FieldMetaData.MANY_TO_ONE) {
if (!hasJoinTable(field))

View File

@ -87,7 +87,7 @@ public class HandlerRelationMapTableFieldStrategy
union.select(new Union.Selector() {
public void select(Select sel, int idx) {
sel.select(_kcols);
if (field.isUni1ToMFK()) {
if (field.isUnidirectionalOneToManyForeignKey()) {
sel.whereForeignKey(field.getElementMapping().getForeignKey(),
sm.getObjectId(), field.getElementMapping().getDeclaredTypeMapping(), store);
sel.select(vals[idx], field.getElementMapping().
@ -146,10 +146,11 @@ public class HandlerRelationMapTableFieldStrategy
throw new MetaDataException(_loc.get("not-relation", val));
FieldMapping mapped = field.getMappedByMapping();
if (field.isUni1ToMFK() || (!field.isBiMTo1JT() && mapped != null)) {
if (field.isUnidirectionalOneToManyForeignKey()
|| (!field.isBidirectionalManyToOneJoinTable() && mapped != null)) {
// map to the owner table
handleMappedByForeignKey(adapt);
} else if (field.isBiMTo1JT() || mapped == null) {
} else if (field.isBidirectionalManyToOneJoinTable() || mapped == null) {
// map to a separate table
field.mapJoin(adapt, true);
if (val.getTypeMapping().isMapped()) {
@ -186,11 +187,11 @@ public class HandlerRelationMapTableFieldStrategy
if (map == null || map.isEmpty())
return;
if (!field.isBiMTo1JT() && field.getMappedBy() != null)
if (!field.isBidirectionalManyToOneJoinTable() && field.getMappedBy() != null)
return;
Row row = null;
if (!field.isUni1ToMFK()) {
if (!field.isUnidirectionalOneToManyForeignKey()) {
row = rm.getSecondaryRow(field.getTable(), Row.ACTION_INSERT);
row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(),
sm);
@ -204,7 +205,7 @@ public class HandlerRelationMapTableFieldStrategy
entry = (Map.Entry) itr.next();
valsm = RelationStrategies.getStateManager(entry.getValue(),
ctx);
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
row = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
Row.ACTION_UPDATE, valsm, true);
row.wherePrimaryKey(valsm);
@ -223,7 +224,7 @@ public class HandlerRelationMapTableFieldStrategy
// from the view point of the owned side
PersistenceCapable obj = sm.getPersistenceCapable();
if (!populateKey(row, valsm, obj, ctx, rm, store)) {
if (!field.isUni1ToMFK())
if (!field.isUnidirectionalOneToManyForeignKey())
rm.flushSecondaryRow(row);
}
}
@ -238,7 +239,7 @@ public class HandlerRelationMapTableFieldStrategy
public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
if (field.getMappedBy() != null && !field.isBiMTo1JT())
if (field.getMappedBy() != null && !field.isBidirectionalManyToOneJoinTable())
return;
Map map = (Map) sm.fetchObject(field.getIndex());
@ -269,7 +270,7 @@ public class HandlerRelationMapTableFieldStrategy
Object mkey;
if (canChange && !change.isEmpty()) {
Row changeRow = null;
if (!field.isUni1ToMFK()) {
if (!field.isUnidirectionalOneToManyForeignKey()) {
changeRow = rm.getSecondaryRow(field.getTable(),
Row.ACTION_UPDATE);
changeRow.whereForeignKey(field.getJoinForeignKey(), sm);
@ -278,7 +279,7 @@ public class HandlerRelationMapTableFieldStrategy
for (Iterator itr = change.iterator(); itr.hasNext();) {
mkey = itr.next();
valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
changeRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
Row.ACTION_UPDATE, valsm, true);
changeRow.wherePrimaryKey(valsm);
@ -288,7 +289,7 @@ public class HandlerRelationMapTableFieldStrategy
}
HandlerStrategies.where(key, mkey, store, changeRow, _kcols);
if (!field.isUni1ToMFK())
if (!field.isUnidirectionalOneToManyForeignKey())
rm.flushSecondaryRow(changeRow);
}
}
@ -297,14 +298,14 @@ public class HandlerRelationMapTableFieldStrategy
Collection rem = ct.getRemoved();
if (!rem.isEmpty() || (!canChange && !change.isEmpty())) {
Row delRow = null;
if (!field.isUni1ToMFK()) {
if (!field.isUnidirectionalOneToManyForeignKey()) {
delRow = rm.getSecondaryRow(field.getTable(),
Row.ACTION_DELETE);
delRow.whereForeignKey(field.getJoinForeignKey(), sm);
}
for (Iterator itr = rem.iterator(); itr.hasNext();) {
mkey = itr.next();
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
updateSetNull(sm, mkey, store, rm);
} else {
HandlerStrategies.where(key, mkey, store, delRow, _kcols);
@ -314,7 +315,7 @@ public class HandlerRelationMapTableFieldStrategy
if (!canChange && !change.isEmpty()) {
for (Iterator itr = change.iterator(); itr.hasNext();) {
mkey = itr.next();
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
updateSetNull(sm, mkey, store, rm);
} else {
HandlerStrategies.where(key, itr.next(), store, delRow, _kcols);
@ -328,7 +329,7 @@ public class HandlerRelationMapTableFieldStrategy
Collection add = ct.getAdded();
if (!add.isEmpty() || (!canChange && !change.isEmpty())) {
Row addRow = null;
if (!field.isUni1ToMFK()) {
if (!field.isUnidirectionalOneToManyForeignKey()) {
addRow = rm.getSecondaryRow(field.getTable(),
Row.ACTION_INSERT);
addRow.setForeignKey(field.getJoinForeignKey(),
@ -337,7 +338,7 @@ public class HandlerRelationMapTableFieldStrategy
for (Iterator itr = add.iterator(); itr.hasNext();) {
mkey = itr.next();
valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
addRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
Row.ACTION_UPDATE, valsm, true);
addRow.wherePrimaryKey(valsm);
@ -348,14 +349,14 @@ public class HandlerRelationMapTableFieldStrategy
HandlerStrategies.set(key, mkey, store, addRow, _kcols,
_kio, true);
if (!field.isUni1ToMFK())
if (!field.isUnidirectionalOneToManyForeignKey())
rm.flushSecondaryRow(addRow);
}
if (!canChange && !change.isEmpty()) {
for (Iterator itr = change.iterator(); itr.hasNext();) {
mkey = itr.next();
valsm = RelationStrategies.getStateManager(map.get(mkey), ctx);
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
addRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
Row.ACTION_UPDATE, valsm, true);
addRow.wherePrimaryKey(valsm);
@ -366,7 +367,7 @@ public class HandlerRelationMapTableFieldStrategy
HandlerStrategies.set(key, mkey, store, addRow, _kcols,
_kio, true);
if (!field.isUni1ToMFK())
if (!field.isUnidirectionalOneToManyForeignKey())
rm.flushSecondaryRow(addRow);
}
}
@ -413,9 +414,9 @@ public class HandlerRelationMapTableFieldStrategy
public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
if ((field.getMappedBy() != null && !field.isBiMTo1JT()))
if ((field.getMappedBy() != null && !field.isBidirectionalManyToOneJoinTable()))
return;
if (field.isUni1ToMFK()) {
if (field.isUnidirectionalOneToManyForeignKey()) {
Map mapObj = (Map)sm.fetchObject(field.getIndex());
updateSetNull(sm, store, rm, mapObj.keySet());
return;

View File

@ -112,10 +112,10 @@ public abstract class MapTableFieldStrategy
throw new MetaDataException(_loc.get("mapped-by-key", field));
// Non-default mapping Uni-/OneToMany/ForeignKey allows schema components
if (field.isUni1ToMFK())
if (field.isUnidirectionalOneToManyForeignKey())
return;
if (field.isBiMTo1JT())
field.setBi1MJoinTableInfo();
if (field.isBidirectionalManyToOneJoinTable())
field.setBidirectionalOneToManyJoinTableInfo();
field.getValueInfo().assertNoSchemaComponents(field, !adapt);
}

View File

@ -28,6 +28,7 @@ import java.util.Set;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.enhance.ReflectingPersistenceCapable;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
@ -37,7 +38,6 @@ import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.FieldStrategy;
import org.apache.openjpa.jdbc.meta.Joinable;
import org.apache.openjpa.jdbc.meta.MappingInfo;
import org.apache.openjpa.jdbc.meta.ValueHandler;
import org.apache.openjpa.jdbc.meta.ValueMapping;
import org.apache.openjpa.jdbc.meta.ValueMappingImpl;
import org.apache.openjpa.jdbc.meta.ValueMappingInfo;
@ -55,13 +55,13 @@ import org.apache.openjpa.jdbc.sql.SQLBuffer;
import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.jdbc.sql.SelectExecutor;
import org.apache.openjpa.jdbc.sql.Union;
import org.apache.openjpa.kernel.LockManager;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.meta.MetaDataModes;
import org.apache.openjpa.util.ApplicationIds;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.InternalException;
@ -74,27 +74,33 @@ import org.apache.openjpa.util.UnsupportedException;
/**
* Mapping for a single-valued relation to another entity.
*
* <br>
* The strategy may reuse the same {@link SelectExecutor select} if the
* {@link JDBCConfiguration#getSelectCacheEnabled() configuration option}
* instructs to do so.
* @author Abe White
* @author Pinaki Poddar (select caching)
* @since 0.4.0
*/
@SuppressWarnings("serial")
public class RelationFieldStrategy
extends AbstractFieldStrategy
implements Joinable, Embeddable {
private static final Localizer _loc = Localizer.forPackage
(RelationFieldStrategy.class);
private static final Localizer _loc = Localizer.forPackage(RelationFieldStrategy.class);
private Boolean _fkOid = null;
private SelectExecutor _executor;
public void map(boolean adapt) {
if (field.getTypeCode() != JavaTypes.PC || field.isEmbeddedPC())
throw new MetaDataException(_loc.get("not-relation", field));
field.getKeyMapping().getValueInfo().assertNoSchemaComponents
(field.getKey(), !adapt);
field.getKeyMapping().getValueInfo().assertNoSchemaComponents(field.getKey(), !adapt);
if (!field.isNonDefaultMappingUsingJoinTableStrategy())
field.getElementMapping().getValueInfo().assertNoSchemaComponents
(field.getElement(), !adapt);
field.getElementMapping().getValueInfo().assertNoSchemaComponents(field.getElement(), !adapt);
boolean criteria = field.getValueInfo().getUseClassCriteria();
// check for named inverse
@ -102,40 +108,33 @@ public class RelationFieldStrategy
if (mapped != null) {
field.getMappingInfo().assertNoSchemaComponents(field, !adapt);
field.getValueInfo().assertNoSchemaComponents(field, !adapt);
mapped.resolve(mapped.MODE_META | mapped.MODE_MAPPING);
mapped.resolve(MetaDataModes.MODE_META | MetaDataModes.MODE_MAPPING);
if (!mapped.isMapped() || mapped.isSerialized())
throw new MetaDataException(_loc.get("mapped-by-unmapped",
field, mapped));
throw new MetaDataException(_loc.get("mapped-by-unmapped", field, mapped));
if (mapped.getTypeCode() == JavaTypes.PC) {
if (mapped.getJoinDirection() == mapped.JOIN_FORWARD) {
field.setJoinDirection(field.JOIN_INVERSE);
field.setColumns(mapped.getDefiningMapping().
getPrimaryKeyColumns());
if (mapped.getJoinDirection() == FieldMapping.JOIN_FORWARD) {
field.setJoinDirection(FieldMapping.JOIN_INVERSE);
field.setColumns(mapped.getDefiningMapping().getPrimaryKeyColumns());
} else if (isTypeUnjoinedSubclass(mapped))
throw new MetaDataException(_loc.get
("mapped-inverse-unjoined", field.getName(),
field.getDefiningMapping(), mapped));
("mapped-inverse-unjoined", field.getName(), field.getDefiningMapping(), mapped));
field.setForeignKey(mapped.getForeignKey
(field.getDefiningMapping()));
field.setForeignKey(mapped.getForeignKey(field.getDefiningMapping()));
} else if (mapped.getElement().getTypeCode() == JavaTypes.PC) {
if (isTypeUnjoinedSubclass(mapped.getElementMapping()))
throw new MetaDataException(_loc.get
("mapped-inverse-unjoined", field.getName(),
field.getDefiningMapping(), mapped));
("mapped-inverse-unjoined", field.getName(), field.getDefiningMapping(), mapped));
// warn the user about making the collection side the owner
Log log = field.getRepository().getLog();
if (log.isInfoEnabled())
log.info(_loc.get("coll-owner", field, mapped));
field.setForeignKey(mapped.getElementMapping().
getForeignKey());
} else
throw new MetaDataException(_loc.get("not-inv-relation",
field, mapped));
field.setForeignKey(mapped.getElementMapping().getForeignKey());
} else {
throw new MetaDataException(_loc.get("not-inv-relation", field, mapped));
}
field.setUseClassCriteria(criteria);
return;
}
@ -157,24 +156,22 @@ public class RelationFieldStrategy
field.getMappingInfo().setColumns(null);
}
if (!field.isBiMTo1JT())
if (!field.isBidirectionalManyToOneJoinTable())
field.mapJoin(adapt, false);
if (field.getTypeMapping().isMapped()) {
if (field.getMappedByIdValue() != null)
setMappedByIdColumns();
if (!field.isBiMTo1JT()) {
ForeignKey fk = vinfo.getTypeJoin(field, field.getName(), true,
adapt);
if (!field.isBidirectionalManyToOneJoinTable()) {
ForeignKey fk = vinfo.getTypeJoin(field, field.getName(), true, adapt);
field.setForeignKey(fk);
}
field.setColumnIO(vinfo.getColumnIO());
if (vinfo.getJoinDirection() == vinfo.JOIN_INVERSE)
field.setJoinDirection(field.JOIN_INVERSE);
} else
RelationStrategies.mapRelationToUnmappedPC(field, field.getName(),
adapt);
if (vinfo.getJoinDirection() == MappingInfo.JOIN_INVERSE)
field.setJoinDirection(FieldMapping.JOIN_INVERSE);
} else {
RelationStrategies.mapRelationToUnmappedPC(field, field.getName(), adapt);
}
field.setUseClassCriteria(criteria);
field.mapPrimaryKey(adapt);
PrimaryKey pk = field.getTable().getPrimaryKey();
@ -209,11 +206,10 @@ public class RelationFieldStrategy
}
}
private List getMappedByIdColumns(FieldMapping pk) {
ClassMetaData embeddedId = ((ValueMappingImpl)pk.getValue()).
getEmbeddedMetaData();
private List<Column> getMappedByIdColumns(FieldMapping pk) {
ClassMetaData embeddedId = ((ValueMappingImpl)pk.getValue()).getEmbeddedMetaData();
Column[] pkCols = null;
List cols = new ArrayList();
List<Column> cols = new ArrayList<Column>();
String mappedByIdValue = field.getMappedByIdValue();
if (embeddedId != null) {
FieldMetaData[] fmds = embeddedId.getFields();
@ -221,20 +217,19 @@ public class RelationFieldStrategy
if ((fmds[i].getName().equals(mappedByIdValue)) ||
mappedByIdValue.length() == 0) {
if (fmds[i].getValue().getEmbeddedMetaData() != null) {
EmbedValueHandler.getEmbeddedIdCols(
(FieldMapping)fmds[i], cols);
} else
EmbedValueHandler.getIdColumns(
(FieldMapping)fmds[i], cols);
EmbedValueHandler.getEmbeddedIdCols((FieldMapping)fmds[i], cols);
} else {
EmbedValueHandler.getIdColumns((FieldMapping)fmds[i], cols);
}
}
}
return cols;
} else { // primary key is single-value
Class pkType = pk.getDeclaredType();
Class<?> pkType = pk.getDeclaredType();
FieldMetaData[] pks = field.getValue().getDeclaredTypeMetaData().
getPrimaryKeyFields();
if (pks.length != 1 || pks[0].getDeclaredType() != pkType)
return Collections.EMPTY_LIST;
return Collections.emptyList();
pkCols = pk.getColumns();
for (int i = 0; i < pkCols.length; i++)
cols.add(pkCols[i]);
@ -271,11 +266,11 @@ public class RelationFieldStrategy
OpenJPAStateManager rel = RelationStrategies.getStateManager
(sm.fetchObjectField(field.getIndex()), store.getContext());
if (field.getJoinDirection() == field.JOIN_INVERSE)
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
updateInverse(sm, rel, store, rm);
else {
Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
if (row != null && !field.isBiMTo1JT()) {
if (row != null && !field.isBidirectionalManyToOneJoinTable()) {
field.setForeignKey(row, rel);
// this is for bi-directional maps, the key and value of the
// map are stored in the table of the mapped-by entity
@ -295,7 +290,7 @@ public class RelationFieldStrategy
if (mapField == null)
return;
Map mapObj = (Map)rel.fetchObjectField(mapField.getIndex());
Map<Object,Object> mapObj = (Map<Object,Object>)rel.fetchObjectField(mapField.getIndex());
Object keyObj = getMapKeyObj(mapObj, sm.getPersistenceCapable());
ValueMapping key = mapField.getKeyMapping();
if (!key.isEmbedded()) {
@ -311,14 +306,11 @@ public class RelationFieldStrategy
} else {
// key is an embeddable or basic type
FieldStrategy strategy = mapField.getStrategy();
if (strategy instanceof
HandlerRelationMapTableFieldStrategy) {
HandlerRelationMapTableFieldStrategy strat =
(HandlerRelationMapTableFieldStrategy) strategy;
if (strategy instanceof HandlerRelationMapTableFieldStrategy) {
HandlerRelationMapTableFieldStrategy strat = (HandlerRelationMapTableFieldStrategy) strategy;
Column[] kcols = strat.getKeyColumns((ClassMapping)meta);
ColumnIO kio = strat.getKeyColumnIO();
HandlerStrategies.set(key, keyObj, store, row, kcols,
kio, true);
HandlerStrategies.set(key, keyObj, store, row, kcols, kio, true);
}
}
}
@ -327,19 +319,18 @@ public class RelationFieldStrategy
FieldMapping[] fields = ((ClassMapping)meta).getFieldMappings();
for (int i = 0; i < fields.length; i++) {
FieldMetaData mappedBy = fields[i].getMappedByMetaData();
if (fields[i].getDeclaredTypeCode() == JavaTypes.MAP &&
mappedBy == field)
if (fields[i].getDeclaredTypeCode() == JavaTypes.MAP && mappedBy == field)
return fields[i];
}
return null;
}
private Object getMapKeyObj(Map mapObj, Object value) {
private Object getMapKeyObj(Map<Object,Object> mapObj, Object value) {
if (value instanceof ReflectingPersistenceCapable)
value = ((ReflectingPersistenceCapable)value).getManagedInstance();
Set<Map.Entry> entries = mapObj.entrySet();
for (Map.Entry entry : entries) {
Set<Map.Entry<Object,Object>> entries = mapObj.entrySet();
for (Map.Entry<Object,Object> entry : entries) {
if (entry.getValue() == value)
return entry.getKey();
}
@ -355,7 +346,7 @@ public class RelationFieldStrategy
OpenJPAStateManager rel = RelationStrategies.getStateManager
(sm.fetchObjectField(field.getIndex()), store.getContext());
if (field.getJoinDirection() == field.JOIN_INVERSE) {
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE) {
nullInverse(sm, rm);
updateInverse(sm, rel, store, rm);
} else {
@ -363,22 +354,22 @@ public class RelationFieldStrategy
field.isBidirectionalJoinTableMappingNonOwner()) ?
Row.ACTION_DELETE : Row.ACTION_UPDATE;
Row row = field.getRow(sm, store, rm, action);
if (row != null && !field.isBiMTo1JT()) {
if (row != null && !field.isBidirectionalManyToOneJoinTable()) {
field.setForeignKey(row, rel);
// this is for bi-directional maps, the key and value of the
// map are stored in the table of the mapped-by entity
setMapKey(sm, rel, store, row);
}
if (field.isBiMTo1JT()) { // also need to update the join table
if (field.isBidirectionalManyToOneJoinTable()) { // also need to update the join table
PersistenceCapable invPC = (PersistenceCapable)sm.fetchObject(
field.getBi_1ToM_JTField().getIndex());
field.getBidirectionalOneToManyJoinTableField().getIndex());
Row secondaryRow = null;
if (invPC != null) {
secondaryRow = rm.getSecondaryRow(field.getBi1ToMJoinFK().getTable(),
secondaryRow = rm.getSecondaryRow(field.getBidirectionalOneToManyJoinForeignKey().getTable(),
Row.ACTION_INSERT);
secondaryRow.setForeignKey(field.getBi1ToMElemFK(), null, sm);
secondaryRow.setForeignKey(field.getBi1ToMJoinFK(), null,
secondaryRow.setForeignKey(field.getBidirectionalOneToManyElementForeignKey(), null, sm);
secondaryRow.setForeignKey(field.getBidirectionalOneToManyJoinForeignKey(), null,
RelationStrategies.getStateManager(invPC,
store.getContext()));
rm.flushSecondaryRow(secondaryRow);
@ -392,7 +383,7 @@ public class RelationFieldStrategy
if (field.getMappedBy() != null)
return;
if (field.getJoinDirection() == field.JOIN_INVERSE) {
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE) {
if (sm.getLoaded().get(field.getIndex())) {
OpenJPAStateManager rel = RelationStrategies.getStateManager(sm.
fetchObjectField(field.getIndex()), store.getContext());
@ -504,7 +495,7 @@ public class RelationFieldStrategy
public int supportsSelect(Select sel, int type, OpenJPAStateManager sm,
JDBCStore store, JDBCFetchConfiguration fetch) {
if (type == Select.TYPE_JOINLESS)
return (field.getJoinDirection() != field.JOIN_INVERSE
return (field.getJoinDirection() != FieldMapping.JOIN_INVERSE
&& sel.isSelected(field.getTable())) ? 1 : 0;
if (type == Select.TYPE_TWO_PART)
return 1;
@ -535,17 +526,15 @@ public class RelationFieldStrategy
final OpenJPAStateManager sm, final JDBCStore store,
final JDBCFetchConfiguration fetch, final int eagerMode) {
final ClassMapping[] clss = field.getIndependentTypeMappings();
if (!(sel instanceof Union))
if (!(sel instanceof Union)) {
selectEagerParallel((Select) sel, clss[0], store, fetch, eagerMode);
else {
} else {
Union union = (Union) sel;
if (fetch.getSubclassFetchMode (field.getTypeMapping())
!= JDBCFetchConfiguration.EAGER_JOIN)
if (fetch.getSubclassFetchMode (field.getTypeMapping()) != JDBCFetchConfiguration.EAGER_JOIN)
union.abortUnion();
union.select(new Union.Selector() {
public void select(Select sel, int idx) {
selectEagerParallel(sel, clss[idx], store, fetch,
eagerMode);
selectEagerParallel(sel, clss[idx], store, fetch, eagerMode);
}
});
}
@ -556,7 +545,7 @@ public class RelationFieldStrategy
*/
private void selectEagerParallel(Select sel, ClassMapping cls,
JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
if (field.isBiMTo1JT())
if (field.isBidirectionalManyToOneJoinTable())
return;
sel.selectPrimaryKey(field.getDefiningMapping());
// set a variable name that does not conflict with any in the query;
@ -571,7 +560,7 @@ public class RelationFieldStrategy
public void selectEagerJoin(Select sel, OpenJPAStateManager sm,
JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
if (field.isBiMTo1JT())
if (field.isBidirectionalManyToOneJoinTable())
return;
// limit the eager mode to single on recursive eager fetching b/c
@ -590,7 +579,7 @@ public class RelationFieldStrategy
* Add the joins needed to select/load eager data.
*/
private Joins eagerJoin(Joins joins, ClassMapping cls, boolean forceInner) {
boolean inverse = field.getJoinDirection() == field.JOIN_INVERSE;
boolean inverse = field.getJoinDirection() == FieldMapping.JOIN_INVERSE;
if (!inverse) {
joins = join(joins, false);
joins = setEmbeddedVariable(joins);
@ -618,7 +607,7 @@ public class RelationFieldStrategy
public int select(Select sel, OpenJPAStateManager sm, JDBCStore store,
JDBCFetchConfiguration fetch, int eagerMode) {
if (field.getJoinDirection() == field.JOIN_INVERSE)
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
return -1;
// already cached oid?
if (sm != null && sm.getIntermediate(field.getIndex()) != null)
@ -633,11 +622,11 @@ public class RelationFieldStrategy
JDBCFetchConfiguration fetch, Object res)
throws SQLException {
// process batched results if we haven't already
Map rels;
Map<Object,Object> rels;
if (res instanceof Result)
rels = processEagerParallelResult(sm, store, fetch, (Result) res);
else
rels = (Map) res;
rels = (Map<Object,Object>) res;
// store object for this oid in instance
sm.storeObject(field.getIndex(), rels.remove(sm.getObjectId()));
@ -647,7 +636,7 @@ public class RelationFieldStrategy
/**
* Process the given batched result.
*/
private Map processEagerParallelResult(OpenJPAStateManager sm,
private Map<Object,Object> processEagerParallelResult(OpenJPAStateManager sm,
JDBCStore store, JDBCFetchConfiguration fetch, Result res)
throws SQLException {
// do same joins as for load
@ -657,7 +646,7 @@ public class RelationFieldStrategy
Joins joins = res.newJoins().setVariable("*");
eagerJoin(joins, clss[0], true);
Map rels = new HashMap();
Map<Object,Object> rels = new HashMap<Object,Object>();
ClassMapping owner = field.getDefiningMapping();
ClassMapping cls;
Object oid;
@ -676,7 +665,7 @@ public class RelationFieldStrategy
public void loadEagerJoin(OpenJPAStateManager sm, JDBCStore store,
JDBCFetchConfiguration fetch, Result res)
throws SQLException {
if (field.isBiMTo1JT())
if (field.isBidirectionalManyToOneJoinTable())
return;
ClassMapping cls = field.getIndependentTypeMappings()[0];
@ -719,7 +708,7 @@ public class RelationFieldStrategy
public void load(OpenJPAStateManager sm, JDBCStore store,
JDBCFetchConfiguration fetch, Result res)
throws SQLException {
if (field.getJoinDirection() == field.JOIN_INVERSE)
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
return;
// cached oid?
if (sm != null && sm.getIntermediate(field.getIndex()) != null)
@ -732,7 +721,7 @@ public class RelationFieldStrategy
// get the related object's oid
ClassMapping relMapping = field.getTypeMapping();
Object oid = null;
if (relMapping.isMapped() && !field.isBiMTo1JT()) {
if (relMapping.isMapped() && !field.isBidirectionalManyToOneJoinTable()) {
oid = relMapping.getObjectId(store, res, field.getForeignKey(),
field.getPolymorphic() != ValueMapping.POLY_FALSE, null);
} else {
@ -746,8 +735,7 @@ public class RelationFieldStrategy
if (cols.length == 1) {
Object val = res.getObject(cols[0], null, null);
if (val != null)
oid = ApplicationIds.fromPKValues(new Object[]{ val },
relMapping);
oid = ApplicationIds.fromPKValues(new Object[]{ val }, relMapping);
} else {
Object[] vals = new Object[cols.length];
for (int i = 0; i < cols.length; i++) {
@ -767,8 +755,7 @@ public class RelationFieldStrategy
sm.setIntermediate(field.getIndex(), oid);
}
public void load(final OpenJPAStateManager sm, final JDBCStore store,
final JDBCFetchConfiguration fetch)
public void load(final OpenJPAStateManager sm, final JDBCStore store, final JDBCFetchConfiguration fetch)
throws SQLException {
// check for cached oid value, or load oid if no way to join
if (Boolean.TRUE.equals(_fkOid)) {
@ -787,41 +774,54 @@ public class RelationFieldStrategy
// select related mapping columns; joining from the related type
// back to our fk table if not an inverse mapping (in which case we
// can just make sure the inverse cols == our pk values)
Union union = store.getSQLFactory().newUnion(rels.length);
union.setExpectedResultCount(1, false);
if (fetch.getSubclassFetchMode(field.getTypeMapping())
!= JDBCFetchConfiguration.EAGER_JOIN)
union.abortUnion();
Union union;
if (_executor == null) {
union = store.getSQLFactory().newUnion(rels.length);
union.setExpectedResultCount(1, false);
if (fetch.getSubclassFetchMode(field.getTypeMapping()) != JDBCFetchConfiguration.EAGER_JOIN)
union.abortUnion();
if (((JDBCConfiguration)field.getMappingRepository().getConfiguration()).getSelectCacheEnabled()) {
_executor = union;
}
} else {
union = (Union)_executor;
}
union.select(new Union.Selector() {
public void select(Select sel, int idx) {
if (field.getJoinDirection() == field.JOIN_INVERSE)
sel.whereForeignKey(field.getForeignKey(rels[idx]),
sm.getObjectId(), field.getDefiningMapping(), store);
else {
if (!field.isBiMTo1JT()) {
resJoins[idx] = sel.newJoins().joinRelation(field.getName(),
field.getForeignKey(rels[idx]), rels[idx],
field.getSelectSubclasses(), false, false);
ForeignKey fk = field.getForeignKey(rels[idx]);
ClassMapping mapping = field.getDefiningMapping();
Object oid = sm.getObjectId();
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE) {
sel.whereForeignKey(fk, oid, mapping, store);
} else {
if (!field.isBidirectionalManyToOneJoinTable()) {
if (sel.isReadOnly()) {
resJoins[idx] = sel.getJoins();
} else {
resJoins[idx] = sel.newJoins().joinRelation(field.getName(), fk, rels[idx],
subs, false, false);
}
field.wherePrimaryKey(sel, sm, store);
} else {
resJoins[idx] = sel.newJoins().joinRelation(null,
field.getBi1ToMJoinFK(), rels[idx],
field.getSelectSubclasses(), false, false);
sel.whereForeignKey(field.getBi1ToMElemFK(), sm.getObjectId(),
field.getDefiningMapping(), store);
if (sel.isReadOnly()) {
resJoins[idx] = sel.getJoins();
} else {
resJoins[idx] = sel.newJoins().joinRelation(null,
field.getBidirectionalOneToManyJoinForeignKey(), rels[idx],
subs, false, false);
}
sel.whereForeignKey(field.getBidirectionalOneToManyElementForeignKey(), oid, mapping, store);
}
}
sel.select(rels[idx], subs, store, fetch, fetch.EAGER_JOIN,
resJoins[idx]);
if (!sel.isReadOnly()) {
sel.select(rels[idx], subs, store, fetch, JDBCFetchConfiguration.EAGER_JOIN, resJoins[idx]);
}
}
});
Result res = union.execute(store, fetch);
try {
Object val = null;
if (res.next())
val = res.load(rels[res.indexOf()], store, fetch,
resJoins[res.indexOf()]);
Object val = (res.next()) ? res.load(rels[res.indexOf()], store, fetch, resJoins[res.indexOf()]) : null;
sm.storeObject(field.getIndex(), val);
} finally {
res.close();
@ -837,7 +837,7 @@ public class RelationFieldStrategy
// because it'll be in the primary table) and see if fk cols are null;
// if inverse, then we have to do a sub-select to see if any inverse
// objects point back to this field's owner
if (field.getJoinDirection() != field.JOIN_INVERSE) {
if (field.getJoinDirection() != FieldMapping.JOIN_INVERSE) {
//### probably need some sort of subselect here on fk constants
joins = join(joins, false);
Column[] cols = field.getColumns();
@ -846,8 +846,9 @@ public class RelationFieldStrategy
else
sql.append(sel.getColumnAlias(cols[0], joins)).
append(" IS ").appendValue(null, cols[0]);
} else
} else {
testInverseNull(sql, sel, joins, true);
}
}
public void appendIsNotNull(SQLBuffer sql, Select sel, Joins joins) {
@ -855,7 +856,7 @@ public class RelationFieldStrategy
// because it'll be in the primary table) and see if fk cols aren't
// null; if inverse, then we have to do a sub-select to see if any
// inverse objects point back to this field's owner
if (field.getJoinDirection() != field.JOIN_INVERSE) {
if (field.getJoinDirection() != FieldMapping.JOIN_INVERSE) {
//### probably need some sort of subselect here on fk constants
joins = join(joins, false);
Column[] cols = field.getColumns();
@ -886,30 +887,27 @@ public class RelationFieldStrategy
sql.append("0 < ");
ForeignKey fk = field.getForeignKey();
ContainerFieldStrategy.appendJoinCount(sql, sel, joins, dict, field,
fk);
ContainerFieldStrategy.appendJoinCount(sql, sel, joins, dict, field, fk);
}
public Joins join(Joins joins, boolean forceOuter) {
// if we're not in an inverse object table join normally, otherwise
// already traversed the relation; just join back to owner table
if (field.getJoinDirection() != field.JOIN_INVERSE)
if (field.getJoinDirection() != FieldMapping.JOIN_INVERSE)
return field.join(joins, forceOuter, false);
ClassMapping[] clss = field.getIndependentTypeMappings();
if (clss.length != 1)
throw RelationStrategies.uninversable(field);
if (forceOuter)
return joins.outerJoinRelation(field.getName(),
field.getForeignKey(), clss[0], field.getSelectSubclasses(),
true, false);
field.getForeignKey(), clss[0], field.getSelectSubclasses(), true, false);
return joins.joinRelation(field.getName(), field.getForeignKey(),
clss[0], field.getSelectSubclasses(), true, false);
}
public Joins joinRelation(Joins joins, boolean forceOuter,
boolean traverse) {
public Joins joinRelation(Joins joins, boolean forceOuter, boolean traverse) {
// if this is an inverse mapping it's already joined to the relation
if (field.getJoinDirection() == field.JOIN_INVERSE)
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
return joins;
ClassMapping[] clss = field.getIndependentTypeMappings();
if (clss.length != 1) {
@ -946,8 +944,7 @@ public class RelationFieldStrategy
long id = res.getLong(col, joins);
if (field.getObjectIdFieldTypeCode() == JavaTypes.LONG)
return id;
return store.newDataStoreId(id, relmapping, field.getPolymorphic()
!= ValueMapping.POLY_FALSE);
return store.newDataStoreId(id, relmapping, field.getPolymorphic() != ValueMapping.POLY_FALSE);
}
if (relmapping.isOpenJPAIdentity())
@ -1000,27 +997,21 @@ public class RelationFieldStrategy
fieldVal = store.getContext().getObjectId(fieldVal);
if (fieldVal instanceof OpenJPAId)
fieldVal = ((OpenJPAId) fieldVal).getIdObject();
if (relmapping.getObjectIdType() != null
&& relmapping.getObjectIdType().isInstance(fieldVal)) {
if (relmapping.getObjectIdType() != null && relmapping.getObjectIdType().isInstance(fieldVal)) {
Object[] pks = ApplicationIds.toPKValues(fieldVal, relmapping);
fieldVal = pks[relmapping.getField(j.getFieldIndex()).
getPrimaryKeyIndex()];
fieldVal = pks[relmapping.getField(j.getFieldIndex()).getPrimaryKeyIndex()];
} else if (relmapping.getObjectIdType() == ObjectId.class &&
relmapping.getPrimaryKeyFieldMappings()[0].getValueMapping().isEmbedded()) {
if (fieldVal == null)
return j.getJoinValue(savedFieldVal, col, store);
return j.getJoinValue(fieldVal, col, store);
return j.getJoinValue((fieldVal == null) ? savedFieldVal : fieldVal, col, store);
}
return j.getJoinValue(fieldVal, col, store);
}
public Object getJoinValue(OpenJPAStateManager sm, Column col,
JDBCStore store) {
public Object getJoinValue(OpenJPAStateManager sm, Column col, JDBCStore store) {
return getJoinValue(sm.fetch(field.getIndex()), col, store);
}
public void setAutoAssignedValue(OpenJPAStateManager sm, JDBCStore store,
Column col, Object autoInc) {
public void setAutoAssignedValue(OpenJPAStateManager sm, JDBCStore store, Column col, Object autoInc) {
throw new UnsupportedException();
}
@ -1048,8 +1039,7 @@ public class RelationFieldStrategy
return UNSUPPORTED;
}
public void loadEmbedded(OpenJPAStateManager sm, JDBCStore store,
JDBCFetchConfiguration fetch, Object val)
public void loadEmbedded(OpenJPAStateManager sm, JDBCStore store, JDBCFetchConfiguration fetch, Object val)
throws SQLException {
ClassMapping relMapping = field.getTypeMapping();
Object oid;
@ -1059,8 +1049,7 @@ public class RelationFieldStrategy
oid = store.newDataStoreId(((Number) val).longValue(), relMapping,
field.getPolymorphic() != ValueMapping.POLY_FALSE);
else {
Object[] pks = (getColumns().length == 1) ? new Object[]{ val }
: (Object[]) val;
Object[] pks = (getColumns().length == 1) ? new Object[]{ val } : (Object[]) val;
boolean nulls = true;
for (int i = 0; nulls && i < pks.length; i++)
nulls = pks[i] == null;
@ -1068,17 +1057,15 @@ public class RelationFieldStrategy
oid = null;
else {
oid = ApplicationIds.fromPKValues(pks, relMapping);
if (field.getPolymorphic() == ValueMapping.POLY_FALSE
&& oid instanceof OpenJPAId) {
((OpenJPAId) oid).setManagedInstanceType(relMapping.
getDescribedType());
if (field.getPolymorphic() == ValueMapping.POLY_FALSE && oid instanceof OpenJPAId) {
((OpenJPAId) oid).setManagedInstanceType(relMapping.getDescribedType());
}
}
}
if (oid == null)
if (oid == null) {
sm.storeObject(field.getIndex(), null);
else {
} else {
if (JavaTypes.maybePC(field.getValue()) &&
field.getElement().getEmbeddedMetaData() == null) {
Object obj = store.find(oid, field, fetch);

View File

@ -82,7 +82,7 @@ public class RelationRelationMapTableFieldStrategy
kunion.select(new Union.Selector() {
public void select(Select sel, int idx) {
ForeignKey joinFK = null;
if (field.isUni1ToMFK()) {
if (field.isUnidirectionalOneToManyForeignKey()) {
ValueMapping val = field.getElementMapping();
ValueMappingInfo vinfo = val.getValueInfo();
Table table = vinfo.getTable(val);
@ -117,7 +117,7 @@ public class RelationRelationMapTableFieldStrategy
vunion.setLRS(lrs);
vunion.select(new Union.Selector() {
public void select(Select sel, int idx) {
if (field.isUni1ToMFK()) {
if (field.isUnidirectionalOneToManyForeignKey()) {
sel.orderBy(field.getKeyMapping().getColumns(), true, true);
sel.select(vals[idx], field.getElementMapping().
getSelectSubclasses(), store, fetch, eagerMode, null);
@ -203,10 +203,11 @@ public class RelationRelationMapTableFieldStrategy
FieldMapping mapped = field.getMappedByMapping();
DBDictionary dict = field.getMappingRepository().getDBDictionary();
DBIdentifier keyName = null;
if (field.isUni1ToMFK() || (!field.isBiMTo1JT() && mapped != null)) {
if (field.isUnidirectionalOneToManyForeignKey()
|| (!field.isBidirectionalManyToOneJoinTable() && mapped != null)) {
handleMappedByForeignKey(adapt);
keyName = dict.getValidColumnName(DBIdentifier.newColumn("vkey"), field.getTable());
} else if (field.isBiMTo1JT() || mapped == null) {
} else if (field.isBidirectionalManyToOneJoinTable() || mapped == null) {
field.mapJoin(adapt, true);
mapTypeJoin(val, DBIdentifier.newColumn("value"), adapt);
keyName = dict.getValidColumnName(DBIdentifier.newColumn("key"), field.getTable());
@ -245,11 +246,11 @@ public class RelationRelationMapTableFieldStrategy
if (map == null || map.isEmpty())
return;
if (!field.isBiMTo1JT() && field.getMappedBy() != null)
if (!field.isBidirectionalManyToOneJoinTable() && field.getMappedBy() != null)
return;
Row row = null;
if (!field.isUni1ToMFK()) {
if (!field.isUnidirectionalOneToManyForeignKey()) {
row = rm.getSecondaryRow(field.getTable(), Row.ACTION_INSERT);
row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(),
sm);
@ -263,7 +264,7 @@ public class RelationRelationMapTableFieldStrategy
entry = (Map.Entry) itr.next();
keysm = RelationStrategies.getStateManager(entry.getKey(), ctx);
valsm = RelationStrategies.getStateManager(entry.getValue(), ctx);
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
row = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
Row.ACTION_UPDATE, valsm, true);
row.wherePrimaryKey(valsm);
@ -281,14 +282,14 @@ public class RelationRelationMapTableFieldStrategy
// from the view point of the owned side
PersistenceCapable obj = sm.getPersistenceCapable();
if (!populateKey(row, valsm, obj, ctx, rm, store))
if (!field.isUni1ToMFK())
if (!field.isUnidirectionalOneToManyForeignKey())
rm.flushSecondaryRow(row);
}
}
public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
if (field.getMappedBy() != null && !field.isBiMTo1JT())
if (field.getMappedBy() != null && !field.isBidirectionalManyToOneJoinTable())
return;
Map map = (Map) sm.fetchObject(field.getIndex());
@ -319,7 +320,7 @@ public class RelationRelationMapTableFieldStrategy
Object mkey;
if (canChange && !change.isEmpty()) {
Row changeRow = null;
if (!field.isUni1ToMFK()) {
if (!field.isUnidirectionalOneToManyForeignKey()) {
changeRow = rm.getSecondaryRow(field.getTable(),
Row.ACTION_UPDATE);
changeRow.whereForeignKey(field.getJoinForeignKey(), sm);
@ -339,7 +340,7 @@ public class RelationRelationMapTableFieldStrategy
keysm = RelationStrategies.getStateManager(mkey, ctx);
valsm = RelationStrategies.getStateManager(mval, ctx);
key.whereForeignKey(changeRow, keysm);
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
changeRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
Row.ACTION_UPDATE, valsm, true);
changeRow.wherePrimaryKey(valsm);
@ -355,7 +356,7 @@ public class RelationRelationMapTableFieldStrategy
Collection rem = ct.getRemoved();
if (!rem.isEmpty() || (!canChange && !change.isEmpty())) {
Row delRow = null;
if (!field.isUni1ToMFK()) {
if (!field.isUnidirectionalOneToManyForeignKey()) {
delRow = rm.getSecondaryRow(field.getTable(),
Row.ACTION_DELETE);
delRow.whereForeignKey(field.getJoinForeignKey(), sm);
@ -363,7 +364,7 @@ public class RelationRelationMapTableFieldStrategy
for (Iterator itr = rem.iterator(); itr.hasNext();) {
Object pc = itr.next();
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
updateSetNull(sm, rm, pc);
} else {
keysm = RelationStrategies.getStateManager(pc, ctx);
@ -374,7 +375,7 @@ public class RelationRelationMapTableFieldStrategy
if (!canChange && !change.isEmpty()) {
for (Iterator itr = change.iterator(); itr.hasNext();) {
Object pc = itr.next();
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
updateSetNull(sm, rm, pc);
} else {
keysm = RelationStrategies.getStateManager(pc, ctx);
@ -389,7 +390,7 @@ public class RelationRelationMapTableFieldStrategy
Collection add = ct.getAdded();
if (!add.isEmpty() || (!canChange && !change.isEmpty())) {
Row addRow = null;
if (!field.isUni1ToMFK()) {
if (!field.isUnidirectionalOneToManyForeignKey()) {
addRow = rm.getSecondaryRow(field.getTable(),
Row.ACTION_INSERT);
addRow.setForeignKey(field.getJoinForeignKey(),
@ -409,7 +410,7 @@ public class RelationRelationMapTableFieldStrategy
continue;
keysm = RelationStrategies.getStateManager(mkey, ctx);
valsm = RelationStrategies.getStateManager(mval, ctx);
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
addRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
Row.ACTION_UPDATE, valsm, true);
addRow.wherePrimaryKey(valsm);
@ -436,7 +437,7 @@ public class RelationRelationMapTableFieldStrategy
continue;
keysm = RelationStrategies.getStateManager(mkey, ctx);
valsm = RelationStrategies.getStateManager(mval, ctx);
if (field.isUni1ToMFK()){
if (field.isUnidirectionalOneToManyForeignKey()){
addRow = rm.getRow(field.getElementMapping().getDeclaredTypeMapping().getTable(),
Row.ACTION_UPDATE, valsm, true);
addRow.wherePrimaryKey(valsm);
@ -503,7 +504,7 @@ public class RelationRelationMapTableFieldStrategy
public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
if (field.isUni1ToMFK()) {
if (field.isUnidirectionalOneToManyForeignKey()) {
Map mapObj = (Map)sm.fetchObject(field.getIndex());
updateSetNull(sm, store, rm, mapObj.keySet());
return;

View File

@ -113,7 +113,7 @@ public abstract class RelationToManyTableFieldStrategy
// Bi-directional oneToMany relation with join table strategy
// ==> should not mapped in the owner's table
if (mapped != null) {
if (!field.isBiMTo1JT()) {
if (!field.isBidirectionalManyToOneJoinTable()) {
if (mapped.getElement().getTypeCode() != JavaTypes.PC) {
throw new MetaDataException(_loc.get("not-inv-relation-coll",
field, mapped));
@ -134,9 +134,9 @@ public abstract class RelationToManyTableFieldStrategy
}
}
if (mapped == null || field.isBiMTo1JT()) {
if (field.isBiMTo1JT())
field.setBi1MJoinTableInfo();
if (mapped == null || field.isBidirectionalManyToOneJoinTable()) {
if (field.isBidirectionalManyToOneJoinTable())
field.setBidirectionalOneToManyJoinTableInfo();
field.mapJoin(adapt, true);
if (elem.getTypeMapping().isMapped()) {
ForeignKey fk = vinfo.getTypeJoin(elem, "element", false, adapt);
@ -157,7 +157,7 @@ public abstract class RelationToManyTableFieldStrategy
public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
if (field.getMappedBy() == null || field.isBiMTo1JT())
if (field.getMappedBy() == null || field.isBidirectionalManyToOneJoinTable())
insert(sm, rm, sm.fetchObject(field.getIndex()));
}
@ -188,7 +188,7 @@ public abstract class RelationToManyTableFieldStrategy
public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
if (field.getMappedBy() != null && !field.isBiMTo1JT())
if (field.getMappedBy() != null && !field.isBidirectionalManyToOneJoinTable())
return;
Object obj = sm.fetchObject(field.getIndex());

View File

@ -26,6 +26,7 @@ import java.util.List;
import java.util.Map;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.ClassMapping;
@ -57,8 +58,13 @@ import org.apache.openjpa.util.Proxy;
* insert/update/delete behavior as well as overriding
* {@link FieldStrategy#toDataStoreValue}, {@link FieldStrategy#join}, and
* {@link FieldStrategy#joinRelation} if necessary.
* <br>
* The strategy may reuse the same {@link SelectExecutor select} if the
* {@link JDBCConfiguration#getSelectCacheEnabled() configuration option}
* instructs to do so.
*
* @author Abe White
* @author Pinaki Poddar (select caching)
*/
@SuppressWarnings("serial")
public abstract class StoreCollectionFieldStrategy
@ -194,6 +200,7 @@ public abstract class StoreCollectionFieldStrategy
private void selectEager(Select sel, ClassMapping elem,
OpenJPAStateManager sm, JDBCStore store, JDBCFetchConfiguration fetch,
int eagerMode, boolean selectOid, boolean outer) {
if (sel.isReadOnly()) return;
// force distinct if there was a to-many join to avoid duplicates, but
// if this is a parallel select don't make distinct based on the
// eager joins alone if the original wasn't distinct
@ -523,7 +530,9 @@ public abstract class StoreCollectionFieldStrategy
Union union;
if (_executor == null) {
union = store.getSQLFactory().newUnion(Math.max(1, elems.length));
_executor = union;
if (store.getConfiguration().getSelectCacheEnabled()) {
_executor = union;
}
} else {
union = (Union)_executor;
}
@ -571,25 +580,24 @@ public abstract class StoreCollectionFieldStrategy
}
/**
* Select data for loading, starting in field table.
* Selects data for loading, starting in field table.
*
*/
protected Joins selectAll(Select sel, ClassMapping elem,
OpenJPAStateManager sm, JDBCStore store, JDBCFetchConfiguration fetch,
int eagerMode) {
OpenJPAStateManager sm, JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
ForeignKey fk = getJoinForeignKey(elem);
Object oid = getObjectIdForJoin(fk, sm);
sel.whereForeignKey(fk, oid, field.getDefiningMapping(), store);
Joins joins;
if (!sel.isReadOnly()) {
// order first, then select so that if the projection introduces
// additional ordering, it will be after our required ordering
field.orderLocal(sel, elem, null);
joins = joinElementRelation(sel.newJoins(), elem);
field.orderRelation(sel, elem, joins);
selectElement(sel, elem, store, fetch, eagerMode, joins);
} else {
joins = joinElementRelation(sel.newJoins(), elem);
if (sel.isReadOnly()) {
return sel.getJoins();
}
// order first, then select so that if the projection introduces
// additional ordering, it will be after our required ordering
field.orderLocal(sel, elem, null);
Joins joins = joinElementRelation(sel.newJoins(), elem);
field.orderRelation(sel, elem, joins);
selectElement(sel, elem, store, fetch, eagerMode, joins);
return joins;
}

View File

@ -1894,7 +1894,8 @@ public class DBDictionary
public SQLBuffer toSelectCount(Select sel) {
SQLBuffer selectSQL = new SQLBuffer(this);
SQLBuffer from;
sel.addJoinClassConditions();
if (!sel.isReadOnly())
sel.addJoinClassConditions();
if (sel.getFromSelect() != null)
from = getFromSelect(sel, false);
else

View File

@ -255,6 +255,8 @@ public class SelectImpl
}
public SQLBuffer toSelect(boolean forUpdate, JDBCFetchConfiguration fetch) {
if (_readOnly)
return _full;
_full = _dict.toSelect(this, forUpdate, fetch);
return _full;
}
@ -378,12 +380,10 @@ public class SelectImpl
throws SQLException {
if (fetch == null)
fetch = store.getFetchConfiguration();
return execute(store.getContext(), store, fetch,
fetch.getReadLockLevel());
return execute(store.getContext(), store, fetch, fetch.getReadLockLevel());
}
public Result execute(JDBCStore store, JDBCFetchConfiguration fetch,
int lockLevel)
public Result execute(JDBCStore store, JDBCFetchConfiguration fetch, int lockLevel)
throws SQLException {
if (fetch == null)
fetch = store.getFetchConfiguration();
@ -394,8 +394,7 @@ public class SelectImpl
* Execute this select in the context of the given store manager. The
* context is passed in separately for profiling purposes.
*/
protected Result execute(StoreContext ctx, JDBCStore store,
JDBCFetchConfiguration fetch, int lockLevel)
protected Result execute(StoreContext ctx, JDBCStore store, JDBCFetchConfiguration fetch, int lockLevel)
throws SQLException {
boolean forUpdate = false;
if (!isAggregate() && _grouping == null) {
@ -678,6 +677,7 @@ public class SelectImpl
}
public void addJoinClassConditions() {
assertMutable();
if (_joins == null || _joins.joins() == null)
return;
@ -806,6 +806,7 @@ public class SelectImpl
}
public void clearSelects() {
assertMutable();
_selects.clear();
}
@ -873,6 +874,7 @@ public class SelectImpl
* to count from the back of the select list.
*/
public void insertPlaceholder(String sql, int pos) {
assertMutable();
Object holder = (_placeholders >= PLACEHOLDERS.length)
? new Placeholder() : PLACEHOLDERS[_placeholders++];
_selects.insertAlias(pos, holder, sql);
@ -882,14 +884,17 @@ public class SelectImpl
* Clear selected placeholders, and return removed select indexes.
*/
public void clearPlaceholderSelects() {
assertMutable();
_selects.clearPlaceholders();
}
public boolean select(Column col) {
assertMutable();
return select(col, (Joins) null);
}
public boolean select(Column col, Joins joins) {
assertMutable();
if (!isGrouping())
return select(col, getJoins(joins, true), false);
groupBy(col, joins);
@ -897,10 +902,12 @@ public class SelectImpl
}
public int select(Column[] cols) {
assertMutable();
return select(cols, null);
}
public int select(Column[] cols, Joins joins) {
assertMutable();
if (cols == null || cols.length == 0)
return 0;
if (isGrouping()) {
@ -919,6 +926,7 @@ public class SelectImpl
* Select the given column after making the given joins.
*/
private boolean select(Column col, PathJoins pj, boolean ident) {
assertMutable();
// we cache on column object if there are no joins so that when
// looking up columns in the result we don't have to create a string
// buffer for the table + column alias; if there are joins, then
@ -940,12 +948,14 @@ public class SelectImpl
public void select(ClassMapping mapping, int subclasses,
JDBCStore store, JDBCFetchConfiguration fetch, int eager) {
assertMutable();
select(mapping, subclasses, store, fetch, eager, null);
}
public void select(ClassMapping mapping, int subclasses,
JDBCStore store, JDBCFetchConfiguration fetch, int eager,
Joins joins) {
assertMutable();
select(this, mapping, subclasses, store, fetch, eager, joins, false);
}
@ -994,10 +1004,12 @@ public class SelectImpl
}
public boolean selectIdentifier(Column col) {
assertMutable();
return selectIdentifier(col, (Joins) null);
}
public boolean selectIdentifier(Column col, Joins joins) {
assertMutable();
if (!isGrouping())
return select(col, getJoins(joins, true), true);
groupBy(col, joins);
@ -1005,10 +1017,12 @@ public class SelectImpl
}
public int selectIdentifier(Column[] cols) {
assertMutable();
return selectIdentifier(cols, null);
}
public int selectIdentifier(Column[] cols, Joins joins) {
assertMutable();
if (cols == null || cols.length == 0)
return 0;
if (isGrouping()) {
@ -1025,20 +1039,24 @@ public class SelectImpl
public void selectIdentifier(ClassMapping mapping, int subclasses,
JDBCStore store, JDBCFetchConfiguration fetch, int eager) {
assertMutable();
selectIdentifier(mapping, subclasses, store, fetch, eager, null);
}
public void selectIdentifier(ClassMapping mapping, int subclasses,
JDBCStore store, JDBCFetchConfiguration fetch, int eager,
Joins joins) {
assertMutable();
select(this, mapping, subclasses, store, fetch, eager, joins, true);
}
public int selectPrimaryKey(ClassMapping mapping) {
assertMutable();
return selectPrimaryKey(mapping, null);
}
public int selectPrimaryKey(ClassMapping mapping, Joins joins) {
assertMutable();
return primaryKeyOperation(mapping, true, null, joins, false);
}
@ -1047,6 +1065,7 @@ public class SelectImpl
*/
private int primaryKeyOperation(ClassMapping mapping, boolean sel,
Boolean asc, Joins joins, boolean aliasOrder) {
assertMutable();
if (!sel && asc == null)
return 0;
@ -1134,6 +1153,7 @@ public class SelectImpl
* Append ordering information to our internal buffer.
*/
private void appendOrdering(Object orderBy, boolean asc) {
assertMutable();
if (_ordering == null)
_ordering = new SQLBuffer(_dict);
else
@ -1169,10 +1189,12 @@ public class SelectImpl
}
public boolean orderBy(Column col, boolean asc, boolean sel) {
assertMutable();
return orderBy(col, asc, null, sel);
}
public boolean orderBy(Column col, boolean asc, Joins joins, boolean sel) {
assertMutable();
return orderBy(col, asc, joins, sel, false);
}
@ -1181,15 +1203,18 @@ public class SelectImpl
*/
boolean orderBy(Column col, boolean asc, Joins joins, boolean sel,
boolean aliasOrder) {
assertMutable();
return columnOperation(col, sel, (asc) ? Boolean.TRUE : Boolean.FALSE,
getJoins(joins, true), aliasOrder);
}
public int orderBy(Column[] cols, boolean asc, boolean sel) {
assertMutable();
return orderBy(cols, asc, null, sel);
}
public int orderBy(Column[] cols, boolean asc, Joins joins, boolean sel) {
assertMutable();
return orderBy(cols, asc, joins, sel, false);
}
@ -1198,6 +1223,7 @@ public class SelectImpl
*/
int orderBy(Column[] cols, boolean asc, Joins joins, boolean sel,
boolean aliasOrder) {
assertMutable();
PathJoins pj = getJoins(joins, true);
int seld = 0;
for (int i = 0; i < cols.length; i++)
@ -1207,29 +1233,28 @@ public class SelectImpl
return seld;
}
public boolean orderBy(SQLBuffer sql, boolean asc, boolean sel, Value selAs)
{
public boolean orderBy(SQLBuffer sql, boolean asc, boolean sel, Value selAs) {
assertMutable();
return orderBy(sql, asc, (Joins) null, sel, selAs);
}
public boolean orderBy(SQLBuffer sql, boolean asc, Joins joins,
boolean sel, Value selAs) {
public boolean orderBy(SQLBuffer sql, boolean asc, Joins joins, boolean sel, Value selAs) {
assertMutable();
return orderBy(sql, asc, joins, sel, false, selAs);
}
/**
* Allow unions to set aliases on order columns.
*/
boolean orderBy(SQLBuffer sql, boolean asc, Joins joins, boolean sel,
boolean aliasOrder, Value selAs) {
boolean orderBy(SQLBuffer sql, boolean asc, Joins joins, boolean sel, boolean aliasOrder, Value selAs) {
assertMutable();
return orderBy((Object) sql, asc, joins, sel, aliasOrder, selAs);
}
/**
* Order on a SQL buffer or string.
*/
private boolean orderBy(Object sql, boolean asc, Joins joins, boolean sel,
boolean aliasOrder, Value selAs) {
private boolean orderBy(Object sql, boolean asc, Joins joins, boolean sel, boolean aliasOrder, Value selAs) {
assertMutable();
Object order = sql;
if (aliasOrder) {
@ -1255,22 +1280,25 @@ public class SelectImpl
}
public boolean orderBy(String sql, boolean asc, boolean sel) {
assertMutable();
return orderBy(sql, asc, null, sel);
}
public boolean orderBy(String sql, boolean asc, Joins joins, boolean sel) {
assertMutable();
return orderBy(sql, asc, joins, sel, false);
}
/**
* Allow unions to set aliases on order columns.
*/
boolean orderBy(String sql, boolean asc, Joins joins, boolean sel,
boolean aliasOrder) {
boolean orderBy(String sql, boolean asc, Joins joins, boolean sel, boolean aliasOrder) {
assertMutable();
return orderBy((Object) sql, asc, joins, sel, aliasOrder, null);
}
public void clearOrdering() {
assertMutable();
_ordering = null;
_orders = 0;
}
@ -1279,9 +1307,9 @@ public class SelectImpl
* Allow unions to record the select list indexes of items we order by.
*/
void setRecordOrderedIndexes(boolean record) {
if (record)
if (record) {
_flags |= RECORD_ORDERED;
else {
} else {
_ordered = null;
_flags &= ~RECORD_ORDERED;
}
@ -1300,8 +1328,7 @@ public class SelectImpl
return idxs;
}
public void wherePrimaryKey(Object oid, ClassMapping mapping,
JDBCStore store) {
public void wherePrimaryKey(Object oid, ClassMapping mapping, JDBCStore store) {
wherePrimaryKey(oid, mapping, null, store);
}
@ -1311,8 +1338,7 @@ public class SelectImpl
* primary key, we will recursively join to its superclass until we find
* an ancestor that does.
*/
private void wherePrimaryKey(Object oid, ClassMapping mapping, Joins joins,
JDBCStore store) {
private void wherePrimaryKey(Object oid, ClassMapping mapping, Joins joins, JDBCStore store) {
// if this mapping's identifiers include something other than
// the pk values, join to super and recurse
if (!mapping.isPrimaryKeyObjectId(false)) {
@ -1325,12 +1351,10 @@ public class SelectImpl
}
Column[] cols = mapping.getPrimaryKeyColumns();
where(oid, mapping, cols, cols, null, null, getJoins(joins, true),
store);
where(oid, mapping, cols, cols, null, null, getJoins(joins, true), store);
}
public void whereForeignKey(ForeignKey fk, Object oid,
ClassMapping mapping, JDBCStore store) {
public void whereForeignKey(ForeignKey fk, Object oid, ClassMapping mapping, JDBCStore store) {
whereForeignKey(fk, oid, mapping, null, store);
}
@ -1340,8 +1364,7 @@ public class SelectImpl
*
* @see #wherePrimaryKey
*/
private void whereForeignKey(ForeignKey fk, Object oid,
ClassMapping mapping, Joins joins, JDBCStore store) {
private void whereForeignKey(ForeignKey fk, Object oid, ClassMapping mapping, Joins joins, JDBCStore store) {
// if this mapping's identifiers include something other than
// the pk values, or if this foreign key doesn't link to only
// identifiers, join to table and do a getPrimaryKey
@ -1364,8 +1387,7 @@ public class SelectImpl
}
where(oid, mapping, fk.getPrimaryKeyColumns(), fk.getColumns(),
fk.getConstants(), fk.getConstantColumns(),
getJoins(joins, true), store);
fk.getConstants(), fk.getConstantColumns(), getJoins(joins, true), store);
}
/**
@ -1505,10 +1527,12 @@ public class SelectImpl
public void having(SQLBuffer sql) {
assertMutable();
having(sql, (Joins) null);
}
public void having(SQLBuffer sql, Joins joins) {
assertMutable();
having(sql, getJoins(joins, true));
}
@ -1516,6 +1540,7 @@ public class SelectImpl
* Add the given condition to the HAVING clause.
*/
private void having(SQLBuffer sql, PathJoins pj) {
assertMutable();
// no need to use joins...
if (sql == null || sql.isEmpty())
return;
@ -1528,37 +1553,45 @@ public class SelectImpl
}
public void groupBy(SQLBuffer sql) {
assertMutable();
groupBy(sql, (Joins) null);
}
public void groupBy(SQLBuffer sql, Joins joins) {
assertMutable();
getJoins(joins, true);
groupByAppend(sql.getSQL());
}
public void groupBy(String sql) {
assertMutable();
groupBy(sql, (Joins) null);
}
public void groupBy(String sql, Joins joins) {
assertMutable();
getJoins(joins, true);
groupByAppend(sql);
}
public void groupBy(Column col) {
assertMutable();
groupBy(col, null);
}
public void groupBy(Column col, Joins joins) {
assertMutable();
PathJoins pj = getJoins(joins, true);
groupByAppend(getColumnAlias(col, pj));
}
public void groupBy(Column[] cols) {
assertMutable();
groupBy(cols, null);
}
public void groupBy(Column[] cols, Joins joins) {
assertMutable();
PathJoins pj = getJoins(joins, true);
for (int i = 0; i < cols.length; i++) {
groupByAppend(getColumnAlias(cols[i], pj));
@ -1566,6 +1599,7 @@ public class SelectImpl
}
private void groupByAppend(String sql) {
assertMutable();
if (_grouped == null || !_grouped.contains(sql)) {
if (_grouping == null) {
_grouping = new SQLBuffer(_dict);
@ -1580,11 +1614,13 @@ public class SelectImpl
public void groupBy(ClassMapping mapping, int subclasses, JDBCStore store,
JDBCFetchConfiguration fetch) {
assertMutable();
groupBy(mapping, subclasses, store, fetch, null);
}
public void groupBy(ClassMapping mapping, int subclasses, JDBCStore store,
JDBCFetchConfiguration fetch, Joins joins) {
assertMutable();
// we implement this by putting ourselves into grouping mode, where
// all select invocations are re-routed to group-by invocations instead.
// this allows us to utilize the same select APIs of the store manager
@ -1593,8 +1629,7 @@ public class SelectImpl
boolean wasGrouping = isGrouping();
_flags |= GROUPING;
try {
select(mapping, subclasses, store, fetch,
EagerFetchModes.EAGER_NONE, joins);
select(mapping, subclasses, store, fetch, EagerFetchModes.EAGER_NONE, joins);
} finally {
if (!wasGrouping)
_flags &= ~GROUPING;
@ -1627,7 +1662,7 @@ public class SelectImpl
else if (!pre) {
if ((_flags & OUTER) != 0)
pj = (PathJoins) outer(pj);
if (record) {
if (record && !_readOnly) {
if (!pj.isEmpty()) {
if (_joins == null)
_joins = new SelectJoins(this);
@ -1818,6 +1853,7 @@ public class SelectImpl
}
public void append(SQLBuffer buf, Joins joins) {
assertMutable();
if (joins == null || joins.isEmpty())
return;
if (_joinSyntax == JoinSyntaxes.SYNTAX_SQL92)
@ -1846,6 +1882,7 @@ public class SelectImpl
}
public Joins and(Joins joins1, Joins joins2) {
assertMutable();
return and((PathJoins) joins1, (PathJoins) joins2, true);
}
@ -1857,6 +1894,7 @@ public class SelectImpl
* Combine the given joins.
*/
private SelectJoins and(PathJoins j1, PathJoins j2, boolean nullJoins) {
assertMutable();
if ((j1 == null || j1.isEmpty())
&& (j2 == null || j2.isEmpty()))
return null;
@ -1894,6 +1932,7 @@ public class SelectImpl
}
public Joins or(Joins joins1, Joins joins2) {
assertMutable();
PathJoins j1 = (PathJoins) joins1;
PathJoins j2 = (PathJoins) joins2;
@ -2190,32 +2229,38 @@ public class SelectImpl
}
public Joins join(ForeignKey fk, boolean inverse, boolean toMany) {
assertMutable();
return new SelectJoins(this).join(fk, inverse, toMany);
}
public Joins outerJoin(ForeignKey fk, boolean inverse, boolean toMany) {
assertMutable();
return new SelectJoins(this).outerJoin(fk, inverse, toMany);
}
public Joins joinRelation(String name, ForeignKey fk, ClassMapping target,
int subs, boolean inverse, boolean toMany) {
assertMutable();
return new SelectJoins(this).joinRelation(name, fk, target, subs,
inverse, toMany);
}
public Joins outerJoinRelation(String name, ForeignKey fk,
ClassMapping target, int subs, boolean inverse, boolean toMany) {
assertMutable();
return new SelectJoins(this).outerJoinRelation(name, fk, target, subs,
inverse, toMany);
}
public Joins setVariable(String var) {
assertMutable();
if (var == null)
return this;
return new SelectJoins(this).setVariable(var);
}
public Joins setSubselect(String alias) {
assertMutable();
if (alias == null)
return this;
return new SelectJoins(this).setSubselect(alias);
@ -2312,6 +2357,10 @@ public class SelectImpl
*/
public void setSelect(SelectImpl sel) {
_sel = sel;
if (_sel.isReadOnly()) {
_preJoins = new Stack<Joins>();
_preJoins.push(_sel.getJoins());
}
}
public Object getEager(FieldMapping key) {
@ -3016,6 +3065,7 @@ public class SelectImpl
}
protected Selects newSelects() {
assertMutable();
return new Selects();
}
@ -3235,6 +3285,7 @@ public class SelectImpl
}
public void moveJoinsToParent() {
assertMutable();
}
/**

View File

@ -27,19 +27,20 @@ import java.util.Comparator;
* @author Abe White
* @nojavadoc
*/
@SuppressWarnings("serial")
public class InheritanceComparator
implements Comparator, Serializable {
private Class _base = Object.class;
private Class<?> _base = Object.class;
/**
* Set the least-derived type possible; defaults to <code>null</code>.
*/
public void setBase(Class base) {
public void setBase(Class<?> base) {
_base = base;
}
public Class getBase() {
public Class<?> getBase() {
return _base;
}
@ -47,8 +48,8 @@ public class InheritanceComparator
* Subclasses can override this method to extract the class to compare
* on from the elements of the collection.
*/
protected Class toClass(Object elem) {
return (Class) elem;
protected Class<?> toClass(Object elem) {
return (Class<?>) elem;
}
public int compare(Object o1, Object o2) {
@ -59,8 +60,8 @@ public class InheritanceComparator
if (o2 == null)
return 1;
Class c1 = toClass(o1);
Class c2 = toClass(o2);
Class<?> c1 = toClass(o1);
Class<?> c2 = toClass(o2);
if (c1 == c2)
return 0;
if (c1 == null)
@ -89,7 +90,7 @@ public class InheritanceComparator
/**
* Count the levels of inheritance between this class and our base class.
*/
private int levels(Class to) {
private int levels(Class<?> to) {
if (to.isInterface())
return to.getInterfaces().length;
for (int i = 0; to != null; i++, to = to.getSuperclass())

View File

@ -25,10 +25,11 @@ package org.apache.openjpa.meta;
* @author Abe White
* @nojavadoc
*/
@SuppressWarnings("serial")
public class MetaDataInheritanceComparator
extends InheritanceComparator {
protected Class toClass(Object elem) {
protected Class<?> toClass(Object elem) {
if (elem == null)
return null;
return ((ClassMetaData) elem).getDescribedType();

View File

@ -106,8 +106,7 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
// system sequence
private SequenceMetaData _sysSeq = null;
// cache of parsed metadata, oid class to class, and interface class
// to metadatas
// cache of parsed metadata, oid class to class, and interface class to metadatas
private Map<Class<?>, ClassMetaData> _metas = new HashMap<Class<?>, ClassMetaData>();
private Map<String, ClassMetaData> _metaStringMap = new ConcurrentHashMap<String, ClassMetaData>();
private Map<Class<?>, Class<?>> _oids = Collections.synchronizedMap(new HashMap<Class<?>, Class<?>>());
@ -124,7 +123,8 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
private Map<Class<?>, Class<?>> _metamodel = Collections.synchronizedMap(new HashMap<Class<?>, Class<?>>());
// map of classes to lists of their subclasses
private Map<Class<?>, List<Class<?>>> _subs = Collections.synchronizedMap(new HashMap<Class<?>, List<Class<?>>>());
private Map<Class<?>, Collection<Class<?>>> _subs =
Collections.synchronizedMap(new HashMap<Class<?>, Collection<Class<?>>>());
// xml mapping
protected final XMLMetaData[] EMPTY_XMLMETAS;
@ -283,7 +283,7 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
}
/**
* Sets whether this repository will load all known persistent classes at initialization.
* Affirms if this repository will load all known persistent classes at initialization.
* Defaults to false.
*/
public boolean getPreload() {
@ -304,11 +304,11 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
* MetaData for all persistent classes and will remove locking from this class.
*/
public synchronized void preload() {
if (_preload == false) {
if (!_preload) {
return;
}
// If pooling EMFs, this method may be invoked more than once. Only perform this work once.
if (_preloadComplete == true) {
if (_preloadComplete) {
return;
}
@ -316,7 +316,7 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
MultiClassLoader multi = AccessController.doPrivileged(J2DoPrivHelper.newMultiClassLoaderAction());
multi.addClassLoader(AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction()));
multi.addClassLoader(AccessController.doPrivileged(J2DoPrivHelper
.getClassLoaderAction(MetaDataRepository.class)));
.getClassLoaderAction(MetaDataRepository.class)));
// If a ClassLoader was passed into Persistence.createContainerEntityManagerFactory on the PersistenceUnitInfo
// we need to add that loader to the chain of classloaders
ClassResolver resolver = _conf.getClassResolverInstance();
@ -359,8 +359,7 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
}
}
// Hook in this class as a listener and process registered classes list to populate _aliases
// list.
// Hook in this class as a listener and process registered classes list to populate _aliases list.
PCRegistry.addRegisterClassListener(this);
processRegisteredClasses(multi);
_locking = false;
@ -856,9 +855,8 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
}
private ClassMetaData[] getMetaDatasInternal() {
// prevent concurrent mod errors when resolving one metadata
// introduces others
ClassMetaData[] metas = (ClassMetaData[]) _metas.values().toArray(new ClassMetaData[_metas.size()]);
// prevent concurrent modification errors when resolving one metadata introduces others
ClassMetaData[] metas = _metas.values().toArray(new ClassMetaData[_metas.size()]);
for (int i = 0; i < metas.length; i++)
if (metas[i] != null)
getMetaData(metas[i].getDescribedType(), metas[i].getEnvClassLoader(), true);
@ -1800,7 +1798,8 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
/**
* Add the given value to the collection cached in the given map under the given key.
*/
private void addToCollection(Map map, Class<?> key, Class<?> value, boolean inheritance) {
private void addToCollection(Map<Class<?>, Collection<Class<?>>> map, Class<?> key, Class<?> value,
boolean inheritance) {
if (_locking) {
synchronized (map) {
addToCollectionInternal(map, key, value, inheritance);
@ -1810,15 +1809,17 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
}
}
private void addToCollectionInternal(Map map, Class<?> key, Class<?> value, boolean inheritance) {
Collection coll = (Collection) map.get(key);
private void addToCollectionInternal(Map<Class<?>, Collection<Class<?>>> map, Class<?> key,
Class<?> value, boolean inheritance) {
Collection<Class<?>> coll = map.get(key);
if (coll == null) {
if (inheritance) {
InheritanceComparator comp = new InheritanceComparator();
comp.setBase(key);
coll = new TreeSet<Class<?>>(comp);
} else
} else {
coll = new LinkedList<Class<?>>();
}
map.put(key, coll);
}
coll.add(value);
@ -1892,7 +1893,7 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
_aliases = new HashMap<String, List<Class<?>>>();
_pawares = new HashMap<Class<?>, NonPersistentMetaData>();
_nonMapped = new HashMap<Class<?>, NonPersistentMetaData>();
_subs = new HashMap<Class<?>, List<Class<?>>>();
_subs = new HashMap<Class<?>, Collection<Class<?>>>();
// Wait till we're done loading MetaData to flip _lock boolean.
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.lib.conf;
/**
* An immutable boolean value can be set only once and can never be modified to a different value.
*
* @author Pinaki Poddar
*
*/
public class ImmutableBooleanValue extends BooleanValue {
private boolean _dirty;
public ImmutableBooleanValue(String prop) {
super(prop);
}
public void set(boolean value) {
if (_dirty) {
if (value != get().booleanValue())
throw new IllegalStateException(this + " can not be changed from " + get() + " to " + value);
} else {
_dirty = true;
super.set(value);
}
}
}

View File

@ -1511,11 +1511,9 @@ public class AnnotationPersistenceMetaDataSerializer
* then name order.
*/
private class FieldComparator
implements Comparator {
implements Comparator<FieldMetaData> {
public int compare(Object o1, Object o2) {
FieldMetaData fmd1 = (FieldMetaData) o1;
FieldMetaData fmd2 = (FieldMetaData) o2;
public int compare(FieldMetaData fmd1, FieldMetaData fmd2) {
if (fmd1.isPrimaryKey()) {
if (fmd2.isPrimaryKey())
return fmd1.compareTo(fmd2);