mirror of https://github.com/apache/openjpa.git
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:
parent
5bb79b9309
commit
1a50b5fe76
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue