OPENJPA-2099. With Pinaki's green light, we're going to back out the changes for OpenJPA-2099 and OpenJPA-2111 so that we can make progress on the OpenJPA 2.2.0 release.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1243702 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Kevin W. Sutter 2012-02-13 21:23:54 +00:00
parent e6d667e6db
commit 2bbbcc9d73
44 changed files with 1363 additions and 2560 deletions

View File

@ -629,26 +629,4 @@ 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.
* <br>
* This setting can be changed once and only once.
*
* @since 2.2.0
*/
public void setSelectCacheEnabled(boolean enable);
}

View File

@ -43,8 +43,6 @@ 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;
@ -89,7 +87,6 @@ public class JDBCConfigurationImpl
public PluginValue driverDataSourcePlugin;
public MappingFactoryValue mappingFactoryPlugin;
public ObjectValue identifierUtilPlugin;
public ImmutableBooleanValue cacheSelect;
// used internally
private String firstUser = null;
@ -353,10 +350,6 @@ public class JDBCConfigurationImpl
identifierUtilPlugin.setString(aliases[0]);
identifierUtilPlugin.setInstantiatingGetter("getIdentifierUtilInstance");
cacheSelect = new ImmutableBooleanValue("jdbc.CachesSelect");
addValue(cacheSelect);
cacheSelect.setDefault("false");
cacheSelect.set(false); // Disable openjpa.CachesSelect until openjpa-2099 is complete
// this static initializer is to get past a weird
// ClassCircularityError that happens only under IBM's
@ -1004,12 +997,4 @@ public class JDBCConfigurationImpl
identifierUtilPlugin.set(util);
}
public boolean getSelectCacheEnabled() {
return cacheSelect.get();
}
public void setSelectCacheEnabled(boolean enable) {
cacheSelect.set(enable);
}
}

View File

@ -83,14 +83,13 @@ import org.apache.openjpa.util.UserException;
* @author Abe White
* @nojavadoc
*/
@SuppressWarnings({ "serial", "deprecation" })
public class JDBCStoreQuery
extends ExpressionStoreQuery {
private static final Table INVALID = new Table();
// add all standard filter and aggregate listeners to these maps
private static final Map<String,FilterListener> _listeners = new HashMap<String, FilterListener>();
private static final Map _listeners = new HashMap();
static {
// deprecated extensions
@ -187,8 +186,8 @@ public class JDBCStoreQuery
ExpContext ctx = new ExpContext(_store, params, fetch);
// add selects with populate WHERE conditions to list
List<Select> sels = new ArrayList<Select>(mappings.length);
List<ClassMapping> selMappings = new ArrayList<ClassMapping>(mappings.length);
List sels = new ArrayList(mappings.length);
List selMappings = new ArrayList(mappings.length);
BitSet subclassBits = new BitSet();
BitSet nextBits = new BitSet();
boolean unionable = createWhereSelects(sels, mappings, selMappings,
@ -336,8 +335,8 @@ public class JDBCStoreQuery
* Generate the selects with WHERE conditions needed to execute the query
* for the given mappings.
*/
private boolean createWhereSelects(List<Select> sels, ClassMapping[] mappings,
List<ClassMapping> selMappings, boolean subclasses, BitSet subclassBits,
private boolean createWhereSelects(List sels, ClassMapping[] mappings,
List selMappings, boolean subclasses, BitSet subclassBits,
BitSet nextBits, ExpressionFactory[] facts, QueryExpressions[] exps,
QueryExpressionsState[] states, ExpContext ctx, int subclassMode) {
Number optHint = (Number) ctx.fetch.getHint
@ -365,12 +364,12 @@ public class JDBCStoreQuery
else if (this.ctx.isUnique())
sel.setExpectedResultCount(1, false);
List<ClassMapping> selectFrom = getJoinedTableMeta(sel);
List selectFrom = getJoinedTableMeta(sel);
int size = 0;
if (selectFrom != null) {
size = selectFrom.size();
for (int j = 0; j < size; j++) {
ClassMapping vert = selectFrom.get(j);
ClassMapping vert = (ClassMapping)selectFrom.get(j);
selMappings.add(vert);
if (j == size - 1) {
nextBits.set(sels.size());
@ -389,7 +388,7 @@ public class JDBCStoreQuery
nextBits.set(sels.size());
sels.add(sel);
} else
sels.add((Select)sel.fullClone(1));
sels.add(sel.fullClone(1));
}
}
@ -401,17 +400,17 @@ public class JDBCStoreQuery
return unionable;
}
private List<ClassMapping> getJoinedTableMeta(Select sel) {
List<ClassMapping> selectFrom = sel.getJoinedTableClassMeta();
List<ClassMapping> exSelectFrom = sel.getExcludedJoinedTableClassMeta();
private List getJoinedTableMeta(Select sel) {
List selectFrom = sel.getJoinedTableClassMeta();
List exSelectFrom = sel.getExcludedJoinedTableClassMeta();
if (exSelectFrom == null)
return selectFrom;
if (selectFrom == null)
return null;
int size = selectFrom.size();
List<ClassMapping> retList = new ArrayList<ClassMapping>(size);
List retList = new ArrayList(size);
for (int i = 0; i < size; i++) {
ClassMapping obj = selectFrom.get(i);
Object obj = selectFrom.get(i);
if (!exSelectFrom.contains(obj))
retList.add(obj);
}
@ -431,15 +430,15 @@ public class JDBCStoreQuery
|| !hasVerticalSubclasses(mapping))
return new ClassMapping[] { mapping };
List<ClassMapping> subs = new ArrayList<ClassMapping>(4);
List subs = new ArrayList(4);
addSubclasses(mapping, subs);
return subs.toArray(new ClassMapping[subs.size()]);
return (ClassMapping[]) subs.toArray(new ClassMapping[subs.size()]);
}
/**
* Recursive helper to add mappings for subclasses to the given list.
*/
private void addSubclasses(ClassMapping mapping, Collection<ClassMapping> subs) {
private void addSubclasses(ClassMapping mapping, Collection subs) {
// possible future optimizations:
// - if no fields in meta or its subclasses (and not in an
// already-selected table) are in the current fetch
@ -700,8 +699,8 @@ public class JDBCStoreQuery
ExpContext ctx = new ExpContext(_store, params, fetch);
// add selects with populate WHERE conditions to list
List<Select> sels = new ArrayList<Select>(mappings.length);
List<ClassMapping> selMappings = new ArrayList<ClassMapping>(mappings.length);
List sels = new ArrayList(mappings.length);
List selMappings = new ArrayList(mappings.length);
BitSet subclassBits = new BitSet();
BitSet nextBits = new BitSet();
boolean unionable = createWhereSelects(sels, mappings, selMappings,
@ -798,11 +797,11 @@ public class JDBCStoreQuery
(org.apache.openjpa.jdbc.kernel.exps.Math) value;
Val value1 = mathVal.getVal1();
Object val1 = getValue(value1, ob, params, sm);
Class<?> c1 = value1.getType();
Class c1 = value1.getType();
Val value2 = mathVal.getVal2();
Object val2 = getValue(value2, ob, params, sm);
Class<?> c2 = value2.getType();
Class c2 = value2.getType();
String op = mathVal.getOperation();
if (op.equals(org.apache.openjpa.jdbc.kernel.exps.Math.ADD))
@ -943,7 +942,7 @@ public class JDBCStoreQuery
org.apache.openjpa.jdbc.kernel.exps.Abs absVal =
(org.apache.openjpa.jdbc.kernel.exps.Abs) value;
Object val = getValue(absVal.getValue(), ob, params, sm);
Class<?> c = val.getClass();
Class c = val.getClass();
if (c == Integer.class)
return Integer.valueOf(java.lang.Math.abs(((Integer) val).intValue()));
else if (c == Float.class)
@ -960,7 +959,7 @@ public class JDBCStoreQuery
org.apache.openjpa.jdbc.kernel.exps.Sqrt sqrtVal =
(org.apache.openjpa.jdbc.kernel.exps.Sqrt) value;
Object val = getValue(sqrtVal.getValue(), ob, params, sm);
Class<?> c = val.getClass();
Class c = val.getClass();
if (c == Integer.class)
return Double.valueOf(java.lang.Math.sqrt(((Integer) val).doubleValue()));
else if (c == Float.class)

View File

@ -32,7 +32,6 @@ import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.MappingRepository;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.sql.BindParameter;
import org.apache.openjpa.jdbc.sql.LogicalUnion;
import org.apache.openjpa.jdbc.sql.SQLBuffer;
import org.apache.openjpa.jdbc.sql.SelectExecutor;
@ -431,10 +430,10 @@ public class PreparedQueryImpl implements PreparedQuery {
}
}
void setParameters(List<BindParameter> list) {
void setParameters(List list) {
Map<Integer, Object> tmp = new HashMap<Integer, Object>();
for (int i = 0; list != null && i < list.size(); i++) {
tmp.put(i, list.get(i).getValue());
tmp.put(i, list.get(i));
}
_template = Collections.unmodifiableMap(tmp);
}

View File

@ -31,7 +31,6 @@ 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;
@ -45,8 +44,6 @@ 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;
@ -63,22 +60,17 @@ 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;
@ -97,9 +89,6 @@ 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.
*/
@ -1120,48 +1109,4 @@ public class ClassMapping
return true;
return false;
}
/**
* Gets the {@link Select select} used for selecting instances of this mapping.
* If {@link JDBCConfiguration#getSelectCacheEnabled() aggressive caching} of
* select statements is enabled, then a select is generated for the first call,
* cached in this mapping and subsequently returned. A cached select becomes
* {@link Select#isReadOnly() immutable} i.e. no structural modification is
* allowed <em>after</em> its corresponding SQL has been executed on the database.
*
* @return a new or cached select to select instances of this mapping.
*/
public Select getSelect() {
Select result = _select;
if (result == null) {
JDBCConfiguration conf = (JDBCConfiguration)getMappingRepository().getConfiguration();
result = conf.getSQLFactoryInstance().newSelect();
if (conf.getSelectCacheEnabled()) {
_select = result;
}
}
return result;
}
/**
* Gets the {@link Union union} used for selecting instances of this mapping.
* If {@link JDBCConfiguration#getSelectCacheEnabled() aggressive caching} of
* union statements is enabled, then a union is generated for the first call,
* cached in this mapping and subsequently returned. A cached union becomes
* {@link Select#isReadOnly() immutable} i.e. no structural modification is
* allowed <em>after</em> its corresponding SQL has been executed on the database.
*
* @return a new or cached union to select instances of this mapping.
*/
public Union getUnion(int selects) {
Union result = _union;
if (result == null) {
JDBCConfiguration conf = (JDBCConfiguration)getMappingRepository().getConfiguration();
result = conf.getSQLFactoryInstance().newUnion(selects);
if (conf.getSelectCacheEnabled()) {
_union = result;
}
}
return result;
}
}

View File

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

View File

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

View File

@ -105,14 +105,15 @@ 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;
@ -259,10 +260,12 @@ public class MappingRepository extends MetaDataRepository {
public QueryResultMapping[] getQueryResultMappings() {
if (_locking) {
synchronized (this) {
return _results.values().toArray(new QueryResultMapping[_results.size()]);
Collection values = _results.values();
return (QueryResultMapping[]) values.toArray(new QueryResultMapping[values.size()]);
}
} else {
return _results.values().toArray(new QueryResultMapping[_results.size()]);
Collection values = _results.values();
return (QueryResultMapping[]) values.toArray(new QueryResultMapping[values.size()]);
}
}
@ -270,7 +273,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));
@ -283,7 +286,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);
@ -293,7 +296,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);
@ -316,7 +319,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)
@ -1005,7 +1008,8 @@ 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);
@ -1020,7 +1024,8 @@ 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);
@ -1043,13 +1048,14 @@ public class MappingRepository extends MetaDataRepository {
FieldMapping mapped = field.getMappedByMapping();
if (mapped != null) {
//bi-/M-1/JoinTable ==> join table strategy
if (isBidirectionalManyToOneJoinTable(field))
if (isBiMTo1JT(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.
@ -1058,84 +1064,82 @@ 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 (isUnidirectionalOneToManyForeignKey(field)) {
if (isUni1ToMFK(field)) {
return true;
}
return useInverseKeyMapping;
}
public boolean isNonDefaultMappingAllowed() {
return getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(getConfiguration());
OpenJPAConfiguration conf = getConfiguration();
return getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(conf);
}
public boolean isUnidirectionalManyToOneJoinTable(FieldMapping field) {
if (isNonDefaultMappingAllowed()
&& field.getAssociationType() == FieldMetaData.MANY_TO_ONE
&& hasJoinTable(field)
&& !isBidirectional(field)) {
public boolean isUniMTo1JT(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 isUnidirectionalOneToOneJoinTable(FieldMapping field) {
if (isNonDefaultMappingAllowed()
&& field.getAssociationType() == FieldMetaData.ONE_TO_ONE
&& hasJoinTable(field)
&& !isBidirectional(field)) {
public boolean isUni1To1JT(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 isBidirectionalOneToOneJoinTable(FieldMapping field) {
if (isNonDefaultMappingAllowed()
&& field.getAssociationType() == FieldMetaData.ONE_TO_ONE
&& hasJoinTable(field)
&& isBidirectional(field)) {
public boolean isBi1To1JT(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 isUnidirectionalOneToManyForeignKey(FieldMapping field) {
if (isNonDefaultMappingAllowed()
&& field.getAssociationType() == FieldMetaData.ONE_TO_MANY
&& hasJoinColumn(field)
&& !isBidirectional(field)) {
public boolean isUni1ToMFK(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 isBidirectionalManyToOneJoinTable(FieldMapping field) {
public boolean isBiMTo1JT(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 (getBidirectionalOneToManyJoinTableField(field) != null)
if (getBi_1ToM_JoinTableField(field) != null)
return true;
}
}
return false;
}
/**
* Gets the inverse field of bidirectional many to one relation using join table strategy
* for the given field.
*/
public FieldMapping getBidirectionalOneToManyJoinTableField(FieldMapping field) {
// return the inverse field of bidirectional many to one
// relation using join table strategy
public FieldMapping getBi_1ToM_JoinTableField(FieldMapping field) {
if (isNonDefaultMappingAllowed()) {
if (field.getAssociationType() == FieldMetaData.ONE_TO_MANY) {
FieldMapping mappedBy = field.getMappedByMapping();
@ -1155,10 +1159,9 @@ public class MappingRepository extends MetaDataRepository {
return null;
}
/**
* Gets the owning field of bidirectional one to many relation using join table strategy of the given field.
*/
public FieldMapping getBidirectionalManyToOneJoinTableField(FieldMapping field) {
// return the owning field of bidirectional one to many
// relation using join table strategy
public FieldMapping getBi_MTo1_JoinTableField(FieldMapping field) {
if (isNonDefaultMappingAllowed()) {
if (field.getAssociationType() == FieldMetaData.MANY_TO_ONE) {
if (!hasJoinTable(field))

View File

@ -37,10 +37,8 @@ import org.apache.openjpa.jdbc.sql.Row;
import org.apache.openjpa.jdbc.sql.RowManager;
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.kernel.OpenJPAStateManager;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.ThreadGate;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.meta.ValueStrategies;
import org.apache.openjpa.util.InternalException;
@ -51,25 +49,22 @@ import org.apache.openjpa.util.UserException;
* Mapping for a single-valued field that delegates to a {@link ValueHandler}.
*
* @author Abe White
* @author Pinaki Poddar (select cache)
* @since 0.4.0
*/
@SuppressWarnings("serial")
public class HandlerFieldStrategy
extends AbstractFieldStrategy
implements Joinable, Embeddable {
private static final Object NULL = new Object();
private static final Localizer _loc = Localizer.forPackage(HandlerFieldStrategy.class);
private static final Localizer _loc = Localizer.forPackage
(HandlerFieldStrategy.class);
protected Column[] _cols = null;
protected ColumnIO _io = null;
protected Object[] _args = null;
protected boolean _load = false;
protected boolean _lob = false;
private Select _executor;
private ThreadGate _lock = new ThreadGate();
public void map(boolean adapt) {
if (field.getHandler() == null)
@ -225,34 +220,21 @@ public class HandlerFieldStrategy
return;
}
}
Select sel;
Select sel = store.getSQLFactory().newSelect();
sel.select(_cols);
field.wherePrimaryKey(sel, sm, store);
Result res = sel.execute(store, fetch);
Object val = null;
try {
_lock.lock();
if (_executor == null) {
sel = store.getSQLFactory().newSelect();
if (store.getConfiguration().getSelectCacheEnabled()) {
_executor = sel;
}
sel.select(_cols);
} else {
sel = _executor;
}
field.wherePrimaryKey(sel, sm, store);
Result res = sel.execute(store, fetch);
Object val = null;
try {
if (res.next())
val = HandlerStrategies.loadDataStore(field, res, null, _cols);
} finally {
res.close();
}
loadEmbedded(sm, store, fetch, val);
if (res.next())
val = HandlerStrategies.loadDataStore(field, res, null, _cols);
} finally {
_lock.unlock();
res.close();
}
loadEmbedded(sm, store, fetch, val);
}
public Object toDataStoreValue(Object val, JDBCStore store) {

View File

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

View File

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

View File

@ -28,7 +28,6 @@ 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;
@ -38,6 +37,7 @@ 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,14 +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.lib.util.ThreadGate;
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;
@ -75,34 +74,27 @@ 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;
private ThreadGate _lock = new ThreadGate();
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
@ -110,33 +102,40 @@ public class RelationFieldStrategy
if (mapped != null) {
field.getMappingInfo().assertNoSchemaComponents(field, !adapt);
field.getValueInfo().assertNoSchemaComponents(field, !adapt);
mapped.resolve(MetaDataModes.MODE_META | MetaDataModes.MODE_MAPPING);
mapped.resolve(mapped.MODE_META | mapped.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() == FieldMapping.JOIN_FORWARD) {
field.setJoinDirection(FieldMapping.JOIN_INVERSE);
field.setColumns(mapped.getDefiningMapping().getPrimaryKeyColumns());
if (mapped.getJoinDirection() == mapped.JOIN_FORWARD) {
field.setJoinDirection(field.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;
}
@ -158,22 +157,24 @@ public class RelationFieldStrategy
field.getMappingInfo().setColumns(null);
}
if (!field.isBidirectionalManyToOneJoinTable())
if (!field.isBiMTo1JT())
field.mapJoin(adapt, false);
if (field.getTypeMapping().isMapped()) {
if (field.getMappedByIdValue() != null)
setMappedByIdColumns();
if (!field.isBidirectionalManyToOneJoinTable()) {
ForeignKey fk = vinfo.getTypeJoin(field, field.getName(), true, adapt);
if (!field.isBiMTo1JT()) {
ForeignKey fk = vinfo.getTypeJoin(field, field.getName(), true,
adapt);
field.setForeignKey(fk);
}
field.setColumnIO(vinfo.getColumnIO());
if (vinfo.getJoinDirection() == MappingInfo.JOIN_INVERSE)
field.setJoinDirection(FieldMapping.JOIN_INVERSE);
} else {
RelationStrategies.mapRelationToUnmappedPC(field, field.getName(), adapt);
}
if (vinfo.getJoinDirection() == vinfo.JOIN_INVERSE)
field.setJoinDirection(field.JOIN_INVERSE);
} else
RelationStrategies.mapRelationToUnmappedPC(field, field.getName(),
adapt);
field.setUseClassCriteria(criteria);
field.mapPrimaryKey(adapt);
PrimaryKey pk = field.getTable().getPrimaryKey();
@ -208,10 +209,11 @@ public class RelationFieldStrategy
}
}
private List<Column> getMappedByIdColumns(FieldMapping pk) {
ClassMetaData embeddedId = ((ValueMappingImpl)pk.getValue()).getEmbeddedMetaData();
private List getMappedByIdColumns(FieldMapping pk) {
ClassMetaData embeddedId = ((ValueMappingImpl)pk.getValue()).
getEmbeddedMetaData();
Column[] pkCols = null;
List<Column> cols = new ArrayList<Column>();
List cols = new ArrayList();
String mappedByIdValue = field.getMappedByIdValue();
if (embeddedId != null) {
FieldMetaData[] fmds = embeddedId.getFields();
@ -219,19 +221,20 @@ 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.emptyList();
return Collections.EMPTY_LIST;
pkCols = pk.getColumns();
for (int i = 0; i < pkCols.length; i++)
cols.add(pkCols[i]);
@ -268,11 +271,11 @@ public class RelationFieldStrategy
OpenJPAStateManager rel = RelationStrategies.getStateManager
(sm.fetchObjectField(field.getIndex()), store.getContext());
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
if (field.getJoinDirection() == field.JOIN_INVERSE)
updateInverse(sm, rel, store, rm);
else {
Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
if (row != null && !field.isBidirectionalManyToOneJoinTable()) {
if (row != null && !field.isBiMTo1JT()) {
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
@ -292,7 +295,7 @@ public class RelationFieldStrategy
if (mapField == null)
return;
Map<Object,Object> mapObj = (Map<Object,Object>)rel.fetchObjectField(mapField.getIndex());
Map mapObj = (Map)rel.fetchObjectField(mapField.getIndex());
Object keyObj = getMapKeyObj(mapObj, sm.getPersistenceCapable());
ValueMapping key = mapField.getKeyMapping();
if (!key.isEmbedded()) {
@ -308,11 +311,14 @@ 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);
}
}
}
@ -321,18 +327,19 @@ 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<Object,Object> mapObj, Object value) {
private Object getMapKeyObj(Map mapObj, Object value) {
if (value instanceof ReflectingPersistenceCapable)
value = ((ReflectingPersistenceCapable)value).getManagedInstance();
Set<Map.Entry<Object,Object>> entries = mapObj.entrySet();
for (Map.Entry<Object,Object> entry : entries) {
Set<Map.Entry> entries = mapObj.entrySet();
for (Map.Entry entry : entries) {
if (entry.getValue() == value)
return entry.getKey();
}
@ -348,7 +355,7 @@ public class RelationFieldStrategy
OpenJPAStateManager rel = RelationStrategies.getStateManager
(sm.fetchObjectField(field.getIndex()), store.getContext());
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE) {
if (field.getJoinDirection() == field.JOIN_INVERSE) {
nullInverse(sm, rm);
updateInverse(sm, rel, store, rm);
} else {
@ -356,22 +363,22 @@ public class RelationFieldStrategy
field.isBidirectionalJoinTableMappingNonOwner()) ?
Row.ACTION_DELETE : Row.ACTION_UPDATE;
Row row = field.getRow(sm, store, rm, action);
if (row != null && !field.isBidirectionalManyToOneJoinTable()) {
if (row != null && !field.isBiMTo1JT()) {
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.isBidirectionalManyToOneJoinTable()) { // also need to update the join table
if (field.isBiMTo1JT()) { // also need to update the join table
PersistenceCapable invPC = (PersistenceCapable)sm.fetchObject(
field.getBidirectionalOneToManyJoinTableField().getIndex());
field.getBi_1ToM_JTField().getIndex());
Row secondaryRow = null;
if (invPC != null) {
secondaryRow = rm.getSecondaryRow(field.getBidirectionalOneToManyJoinForeignKey().getTable(),
secondaryRow = rm.getSecondaryRow(field.getBi1ToMJoinFK().getTable(),
Row.ACTION_INSERT);
secondaryRow.setForeignKey(field.getBidirectionalOneToManyElementForeignKey(), null, sm);
secondaryRow.setForeignKey(field.getBidirectionalOneToManyJoinForeignKey(), null,
secondaryRow.setForeignKey(field.getBi1ToMElemFK(), null, sm);
secondaryRow.setForeignKey(field.getBi1ToMJoinFK(), null,
RelationStrategies.getStateManager(invPC,
store.getContext()));
rm.flushSecondaryRow(secondaryRow);
@ -385,7 +392,7 @@ public class RelationFieldStrategy
if (field.getMappedBy() != null)
return;
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE) {
if (field.getJoinDirection() == field.JOIN_INVERSE) {
if (sm.getLoaded().get(field.getIndex())) {
OpenJPAStateManager rel = RelationStrategies.getStateManager(sm.
fetchObjectField(field.getIndex()), store.getContext());
@ -497,7 +504,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() != FieldMapping.JOIN_INVERSE
return (field.getJoinDirection() != field.JOIN_INVERSE
&& sel.isSelected(field.getTable())) ? 1 : 0;
if (type == Select.TYPE_TWO_PART)
return 1;
@ -528,15 +535,17 @@ 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);
}
});
}
@ -547,7 +556,7 @@ public class RelationFieldStrategy
*/
private void selectEagerParallel(Select sel, ClassMapping cls,
JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
if (field.isBidirectionalManyToOneJoinTable())
if (field.isBiMTo1JT())
return;
sel.selectPrimaryKey(field.getDefiningMapping());
// set a variable name that does not conflict with any in the query;
@ -562,7 +571,7 @@ public class RelationFieldStrategy
public void selectEagerJoin(Select sel, OpenJPAStateManager sm,
JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
if (field.isBidirectionalManyToOneJoinTable())
if (field.isBiMTo1JT())
return;
// limit the eager mode to single on recursive eager fetching b/c
@ -581,7 +590,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() == FieldMapping.JOIN_INVERSE;
boolean inverse = field.getJoinDirection() == field.JOIN_INVERSE;
if (!inverse) {
joins = join(joins, false);
joins = setEmbeddedVariable(joins);
@ -609,7 +618,7 @@ public class RelationFieldStrategy
public int select(Select sel, OpenJPAStateManager sm, JDBCStore store,
JDBCFetchConfiguration fetch, int eagerMode) {
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
if (field.getJoinDirection() == field.JOIN_INVERSE)
return -1;
// already cached oid?
if (sm != null && sm.getIntermediate(field.getIndex()) != null)
@ -624,11 +633,11 @@ public class RelationFieldStrategy
JDBCFetchConfiguration fetch, Object res)
throws SQLException {
// process batched results if we haven't already
Map<Object,Object> rels;
Map rels;
if (res instanceof Result)
rels = processEagerParallelResult(sm, store, fetch, (Result) res);
else
rels = (Map<Object,Object>) res;
rels = (Map) res;
// store object for this oid in instance
sm.storeObject(field.getIndex(), rels.remove(sm.getObjectId()));
@ -638,7 +647,7 @@ public class RelationFieldStrategy
/**
* Process the given batched result.
*/
private Map<Object,Object> processEagerParallelResult(OpenJPAStateManager sm,
private Map processEagerParallelResult(OpenJPAStateManager sm,
JDBCStore store, JDBCFetchConfiguration fetch, Result res)
throws SQLException {
// do same joins as for load
@ -648,7 +657,7 @@ public class RelationFieldStrategy
Joins joins = res.newJoins().setVariable("*");
eagerJoin(joins, clss[0], true);
Map<Object,Object> rels = new HashMap<Object,Object>();
Map rels = new HashMap();
ClassMapping owner = field.getDefiningMapping();
ClassMapping cls;
Object oid;
@ -667,7 +676,7 @@ public class RelationFieldStrategy
public void loadEagerJoin(OpenJPAStateManager sm, JDBCStore store,
JDBCFetchConfiguration fetch, Result res)
throws SQLException {
if (field.isBidirectionalManyToOneJoinTable())
if (field.isBiMTo1JT())
return;
ClassMapping cls = field.getIndependentTypeMappings()[0];
@ -710,7 +719,7 @@ public class RelationFieldStrategy
public void load(OpenJPAStateManager sm, JDBCStore store,
JDBCFetchConfiguration fetch, Result res)
throws SQLException {
if (field.getJoinDirection() == FieldMapping.JOIN_INVERSE)
if (field.getJoinDirection() == field.JOIN_INVERSE)
return;
// cached oid?
if (sm != null && sm.getIntermediate(field.getIndex()) != null)
@ -723,7 +732,7 @@ public class RelationFieldStrategy
// get the related object's oid
ClassMapping relMapping = field.getTypeMapping();
Object oid = null;
if (relMapping.isMapped() && !field.isBidirectionalManyToOneJoinTable()) {
if (relMapping.isMapped() && !field.isBiMTo1JT()) {
oid = relMapping.getObjectId(store, res, field.getForeignKey(),
field.getPolymorphic() != ValueMapping.POLY_FALSE, null);
} else {
@ -737,7 +746,8 @@ 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++) {
@ -757,7 +767,8 @@ 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)) {
@ -776,64 +787,44 @@ 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;
try {
_lock.lock();
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) {
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 {
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);
}
}
if (!sel.isReadOnly()) {
sel.select(rels[idx], subs, store, fetch,
JDBCFetchConfiguration.EAGER_JOIN, resJoins[idx]);
}
}
});
Union union = store.getSQLFactory().newUnion(rels.length);
union.setExpectedResultCount(1, false);
if (fetch.getSubclassFetchMode(field.getTypeMapping())
!= JDBCFetchConfiguration.EAGER_JOIN)
union.abortUnion();
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);
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);
}
}
sel.select(rels[idx], subs, store, fetch, fetch.EAGER_JOIN,
resJoins[idx]);
}
});
Result res = union.execute(store, fetch);
try {
sm.storeObject(field.getIndex(), res.next()
? res.load(rels[res.indexOf()], store, fetch, resJoins[res.indexOf()]) : null);
} finally {
res.close();
}
Result res = union.execute(store, fetch);
try {
Object val = null;
if (res.next())
val = res.load(rels[res.indexOf()], store, fetch,
resJoins[res.indexOf()]);
sm.storeObject(field.getIndex(), val);
} finally {
_lock.unlock();
res.close();
}
}
@ -846,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() != FieldMapping.JOIN_INVERSE) {
if (field.getJoinDirection() != field.JOIN_INVERSE) {
//### probably need some sort of subselect here on fk constants
joins = join(joins, false);
Column[] cols = field.getColumns();
@ -855,9 +846,8 @@ 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) {
@ -865,7 +855,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() != FieldMapping.JOIN_INVERSE) {
if (field.getJoinDirection() != field.JOIN_INVERSE) {
//### probably need some sort of subselect here on fk constants
joins = join(joins, false);
Column[] cols = field.getColumns();
@ -896,27 +886,30 @@ 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() != FieldMapping.JOIN_INVERSE)
if (field.getJoinDirection() != field.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() == FieldMapping.JOIN_INVERSE)
if (field.getJoinDirection() == field.JOIN_INVERSE)
return joins;
ClassMapping[] clss = field.getIndependentTypeMappings();
if (clss.length != 1) {
@ -953,7 +946,8 @@ 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())
@ -1006,21 +1000,27 @@ 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()) {
return j.getJoinValue((fieldVal == null) ? savedFieldVal : fieldVal, col, store);
if (fieldVal == null)
return j.getJoinValue(savedFieldVal, col, store);
return j.getJoinValue(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,7 +1048,8 @@ 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;
@ -1058,7 +1059,8 @@ 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;
@ -1066,15 +1068,17 @@ public class RelationFieldStrategy
oid = null;
else {
oid = ApplicationIds.fromPKValues(pks, relMapping);
if (field.getPolymorphic() == ValueMapping.POLY_FALSE && oid instanceof OpenJPAId) {
((OpenJPAId) oid).setManagedInstanceType(relMapping.getDescribedType());
if (field.getPolymorphic() == ValueMapping.POLY_FALSE
&& oid instanceof OpenJPAId) {
((OpenJPAId) oid).setManagedInstanceType(relMapping.
getDescribedType());
}
}
}
if (oid == null) {
if (oid == null)
sm.storeObject(field.getIndex(), null);
} else {
else {
if (JavaTypes.maybePC(field.getValue()) &&
field.getElement().getEmbeddedMetaData() == null) {
Object obj = store.find(oid, field, fetch);

View File

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

View File

@ -113,7 +113,7 @@ public abstract class RelationToManyTableFieldStrategy
// Bi-directional oneToMany relation with join table strategy
// ==> should not mapped in the owner's table
if (mapped != null) {
if (!field.isBidirectionalManyToOneJoinTable()) {
if (!field.isBiMTo1JT()) {
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.isBidirectionalManyToOneJoinTable()) {
if (field.isBidirectionalManyToOneJoinTable())
field.setBidirectionalOneToManyJoinTableInfo();
if (mapped == null || field.isBiMTo1JT()) {
if (field.isBiMTo1JT())
field.setBi1MJoinTableInfo();
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.isBidirectionalManyToOneJoinTable())
if (field.getMappedBy() == null || field.isBiMTo1JT())
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.isBidirectionalManyToOneJoinTable())
if (field.getMappedBy() != null && !field.isBiMTo1JT())
return;
Object obj = sm.fetchObject(field.getIndex());

View File

@ -26,7 +26,6 @@ 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;
@ -43,7 +42,7 @@ import org.apache.openjpa.jdbc.sql.SelectExecutor;
import org.apache.openjpa.jdbc.sql.Union;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.kernel.StateManagerImpl;
import org.apache.openjpa.lib.util.ThreadGate;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.ChangeTracker;
@ -58,19 +57,11 @@ 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
extends ContainerFieldStrategy {
protected SelectExecutor _executor;
protected ThreadGate _lock = new ThreadGate();
/**
* Return the foreign key used to join to the owning field for the given
@ -103,7 +94,8 @@ public abstract class StoreCollectionFieldStrategy
*
* @see FieldMapping#joinRelation
*/
protected abstract Joins joinElementRelation(Joins joins, ClassMapping elem);
protected abstract Joins joinElementRelation(Joins joins,
ClassMapping elem);
/**
* Join to the owning field table for the given element mapping from
@ -120,9 +112,9 @@ public abstract class StoreCollectionFieldStrategy
* Convert the field value to a collection. Handles collections and
* arrays by default.
*/
protected Collection<?> toCollection(Object val) {
protected Collection toCollection(Object val) {
if (field.getTypeCode() == JavaTypes.COLLECTION)
return (Collection<?>) val;
return (Collection) val;
return JavaTypes.toList(val, field.getElement().getType(), false);
}
@ -166,9 +158,8 @@ public abstract class StoreCollectionFieldStrategy
else {
final ClassMapping[] elems = getIndependentElementMappings(true);
Union union = (Union) sel;
if (union.isReadOnly())
if (fetch.getSubclassFetchMode(field.getElementMapping().
getTypeMapping()) != JDBCFetchConfiguration.EAGER_JOIN)
getTypeMapping()) != fetch.EAGER_JOIN)
union.abortUnion();
union.select(new Union.Selector() {
public void select(Select sel, int idx) {
@ -184,13 +175,13 @@ public abstract class StoreCollectionFieldStrategy
// we limit further eager fetches to joins, because after this point
// the select has been modified such that parallel clones may produce
// invalid sql
if (sel.isReadOnly()) return;
boolean outer = field.getNullValue() != FieldMapping.NULL_EXCEPTION;
// force inner join for inner join fetch
if (fetch.hasFetchInnerJoin(field.getFullName(false)))
outer = false;
selectEager(sel, getDefaultElementMapping(true), sm, store, fetch,
JDBCFetchConfiguration.EAGER_JOIN, false, outer);
JDBCFetchConfiguration.EAGER_JOIN, false,
outer);
}
public boolean isEagerSelectToMany() {
@ -203,8 +194,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
// force distinct if there was a to-many join to avoid dups, but
// if this is a parallel select don't make distinct based on the
// eager joins alone if the original wasn't distinct
if (eagerMode == JDBCFetchConfiguration.EAGER_PARALLEL) {
@ -224,7 +214,8 @@ public abstract class StoreCollectionFieldStrategy
joins = join(joins, elem);
// order, ref cols
if (field.getOrderColumn() != null || field.getOrders().length > 0 || !selectOid) {
if (field.getOrderColumn() != null || field.getOrders().length > 0
|| !selectOid) {
if (outer)
joins = sel.outer(joins);
if (!selectOid) {
@ -362,17 +353,21 @@ public abstract class StoreCollectionFieldStrategy
mappedByValue = owner.getPersistenceCapable();
res.setMappedByFieldMapping(mappedByFieldMapping);
res.setMappedByValue(mappedByValue);
} else if (coll instanceof Collection && !((Collection) coll).isEmpty()) {
} else if (coll instanceof Collection &&
((Collection) coll).size() > 0) {
// Customer (1) <--> Orders(n)
// coll contains the values of the toMany field (Orders)
// get the StateManager of this toMany value
// and find the value of the inverse mappedBy field (Customer)
// for this toMacdny field
PersistenceCapable pc = (PersistenceCapable)((Collection) coll).iterator().next();
OpenJPAStateManager sm1 = (OpenJPAStateManager) pc.pcGetStateManager();
PersistenceCapable pc = (PersistenceCapable)
((Collection) coll).iterator().next();
OpenJPAStateManager sm1 = (OpenJPAStateManager) pc.
pcGetStateManager();
ClassMapping clm = ((ClassMapping) sm1.getMetaData());
FieldMapping fm = (FieldMapping) clm.getField(mappedByFieldMapping.getName());
FieldMapping fm = (FieldMapping) clm.getField(
mappedByFieldMapping.getName());
if (fm == mappedByFieldMapping)
res.setMappedByValue(sm1.fetchObject(fm.getIndex()));
} else {
@ -518,7 +513,8 @@ public abstract class StoreCollectionFieldStrategy
Result res = sel.execute(store, fetch);
try {
res.next();
coll.getChangeTracker().setNextSequence(res.getInt(field) + 1);
coll.getChangeTracker().setNextSequence
(res.getInt(field) + 1);
} finally {
res.close();
}
@ -526,87 +522,72 @@ public abstract class StoreCollectionFieldStrategy
sm.storeObjectField(field.getIndex(), coll);
return;
}
// select data for this state manager
// Select can be configured for reuse. The locking mechanics ensures that
// under reuse scenario, the Select structure is built under a thread gate
// but later usage is unguarded because a reused select is (almost) immutable.
try {
_lock.lock();
final ClassMapping[] elems = getIndependentElementMappings(true);
final Joins[] resJoins = new Joins[Math.max(1, elems.length)];
Union union;
if (_executor == null) {
union = store.getSQLFactory().newUnion(Math.max(1, elems.length));
if (store.getConfiguration().getSelectCacheEnabled()) {
_executor = union;
}
} else {
union = (Union)_executor;
}
union.select(new Union.Selector() {
public void select(Select sel, int idx) {
ClassMapping elem = (elems.length == 0) ? null : elems[idx];
resJoins[idx] = selectAll(sel, elem, sm, store, fetch, JDBCFetchConfiguration.EAGER_PARALLEL);
}
});
// create proxy
Object coll;
ChangeTracker ct = null;
if (field.getTypeCode() == JavaTypes.ARRAY)
coll = new ArrayList();
else {
coll = sm.newProxy(field.getIndex());
if (coll instanceof Proxy)
ct = ((Proxy) coll).getChangeTracker();
}
// select data for this sm
final ClassMapping[] elems = getIndependentElementMappings(true);
final Joins[] resJoins = new Joins[Math.max(1, elems.length)];
Union union = store.getSQLFactory().newUnion
(Math.max(1, elems.length));
union.select(new Union.Selector() {
public void select(Select sel, int idx) {
ClassMapping elem = (elems.length == 0) ? null : elems[idx];
resJoins[idx] = selectAll(sel, elem, sm, store, fetch,
JDBCFetchConfiguration.EAGER_PARALLEL);
}
});
// load values
Result res = union.execute(store, fetch);
try {
int seq = -1;
boolean ordered = ct != null && field.getOrderColumn() != null;
while (res.next()) {
if (ordered) seq = res.getInt(field.getOrderColumn());
setMappedBy(sm.getObjectId(), sm, coll, res);
add(store, coll, loadElement(sm, store, fetch, res, resJoins[res.indexOf()]));
}
if (ordered) ct.setNextSequence(seq + 1);
} finally {
res.close();
}
// set into sm
if (field.getTypeCode() == JavaTypes.ARRAY) {
sm.storeObject(field.getIndex(),
JavaTypes.toArray((Collection<?>) coll, field.getElement().getType()));
} else {
sm.storeObject(field.getIndex(), coll);
}
} finally {
_lock.unlock();
// create proxy
Object coll;
ChangeTracker ct = null;
if (field.getTypeCode() == JavaTypes.ARRAY)
coll = new ArrayList();
else {
coll = sm.newProxy(field.getIndex());
if (coll instanceof Proxy)
ct = ((Proxy) coll).getChangeTracker();
}
// load values
Result res = union.execute(store, fetch);
try {
int seq = -1;
while (res.next()) {
if (ct != null && field.getOrderColumn() != null)
seq = res.getInt(field.getOrderColumn());
setMappedBy(sm.getObjectId(), sm, coll, res);
add(store, coll, loadElement(sm, store, fetch, res,
resJoins[res.indexOf()]));
}
if (ct != null && field.getOrderColumn() != null)
ct.setNextSequence(seq + 1);
} finally {
res.close();
}
// set into sm
if (field.getTypeCode() == JavaTypes.ARRAY)
sm.storeObject(field.getIndex(), JavaTypes.toArray
((Collection) coll, field.getElement().getType()));
else
sm.storeObject(field.getIndex(), coll);
}
/**
* Selects data for loading, starting in field table.
*
* Select 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);
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;
}
@ -643,9 +624,4 @@ public abstract class StoreCollectionFieldStrategy
}
return oid;
}
public String toString() {
return getClass().getSimpleName() + '[' + field.getName() + ']';
}
}

View File

@ -74,7 +74,7 @@ public abstract class AbstractResult
private static final Joins JOINS = new NoOpJoins();
private Map<Object,Object> _eager = null;
private Map _eager = null;
private ClassMapping _base = null;
private int _index = 0;
private boolean _gotEager = false;
@ -86,14 +86,14 @@ public abstract class AbstractResult
private Object _mappedByValue = null;
public Object getEager(FieldMapping key) {
Map<Object,Object> map = getEagerMap(true);
Map map = getEagerMap(true);
return (map == null) ? null : map.get(key);
}
public void putEager(FieldMapping key, Object res) {
Map<Object,Object> map = getEagerMap(false);
Map map = getEagerMap(false);
if (map == null) {
map = new HashMap<Object,Object>();
map = new HashMap();
setEagerMap(map);
}
map.put(key, res);
@ -104,7 +104,7 @@ public abstract class AbstractResult
*
* @param client whether the client is accessing eager information
*/
protected Map<Object,Object> getEagerMap(boolean client) {
protected Map getEagerMap(boolean client) {
if (client)
_gotEager = true;
return _eager;
@ -113,7 +113,7 @@ public abstract class AbstractResult
/**
* Raw eager information.
*/
protected void setEagerMap(Map<Object,Object> eager) {
protected void setEagerMap(Map eager) {
_eager = eager;
}
@ -129,9 +129,11 @@ public abstract class AbstractResult
/**
* Close all results in eager map.
*/
protected void closeEagerMap(Map<Object,Object> eager) {
protected void closeEagerMap(Map eager) {
if (eager != null) {
for (Object res : eager.values()) {
Object res;
for (Iterator itr = eager.values().iterator(); itr.hasNext();) {
res = itr.next();
if (res != this && res instanceof Closeable)
try {
((Closeable) res).close();
@ -889,6 +891,9 @@ public abstract class AbstractResult
return this;
}
public void appendTo(SQLBuffer buf) {
}
public Joins setCorrelatedVariable(String var) {
return this;
}
@ -899,10 +904,5 @@ public abstract class AbstractResult
public void moveJoinsToParent() {
}
@Override
public StringBuilder path() {
return null;
}
}
}

View File

@ -1,112 +0,0 @@
/*
* 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.jdbc.sql;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.lib.util.FlexibleThreadLocal;
/**
* A binding parameter in a SQL statement.
* <br>
* A binding parameter is used in <tt>WHERE</tt> clause. The parameter is identified by an
* immutable key and has a value. The value of a parameter is bound to a thread and hence
* different thread may see different value. These parameters are associated with a {@link Select}
* and they are the only mutable components of an otherwise {@link SelectExecutor#isReadOnly() immutable}
* select.
* <br><b>NOTE:</b>
* The primary assumption of usage is that the binding parameter values to a cached select and
* executing it are carried out in the same (or <em>equivalent</em>) thread.
* <br>
* The parameter is further qualified by whether it is user specified (e.g. from a query parameter)
* or internally generated (e.g. a discriminator value for inheritance join). A database column can
* also be optionally associated with a binding parameter. Currently {@link SQLBuffer#bind(Object, Column)
* rebinding} a parameter to a value is only possible if the parameter is associated with a column.
*
* @see SQLBuffer#appendValue(Object, Column, org.apache.openjpa.kernel.exps.Parameter)
* @see SQLBuffer#bind(Object, Column)
*
* @author Pinaki Poddar
* @since 2.2.0
*/
public class BindParameter {
// Is this parameter specified by user or our own runtime
private final boolean _user;
// the column
private final Column _column;
// key of this parameter
private final Object _key;
private FlexibleThreadLocal _values = new FlexibleThreadLocal();
/**
* Constructs a parameter with given key, column and user flag.
*
* @param key the identifier. Can be null only if not a user-defined parameter.
* @param user flags if this key is originally specified by the user.
* @param column a column represented by this parameter. Can be null.
*/
public BindParameter(Object key, boolean user, Column column, Object value) {
super();
if (user && key == null)
throw new IllegalArgumentException("User-defined parameter can not have null key");
_key = key;
_user = user;
_column = column;
_values.set(value);
}
/**
* Gets the value bound to this parameter for the calling thread. Can be null.
*
* @exception if the current thread or its equivalent never bound a value
* to this parameter.
*/
public Object getValue() {
return _values.get();
}
/**
* Binds the given value to this parameter. Can be null.
*/
public void setValue(Object value) {
_values.set(value);
}
/**
* Affirms if this parameter is specified by the user.
*/
public boolean isUser() {
return _user;
}
/**
* Gets the column associated with this parameter, if any.
*/
public Column getColumn() {
return _column;
}
/**
* Gets the key associated with this parameter.
* The user-defined parameter must have a non-null key.
*/
public Object getKey() {
return _key;
}
}

View File

@ -1399,9 +1399,6 @@ public class DBDictionary
} else if (val instanceof Calendard) {
cald = (Calendard) val;
val = cald.value;
} else if (val instanceof BindParameter) {
BindParameter bParm = (BindParameter) val;
val = bParm.getValue();
}
if (val == null)
@ -1894,8 +1891,7 @@ public class DBDictionary
public SQLBuffer toSelectCount(Select sel) {
SQLBuffer selectSQL = new SQLBuffer(this);
SQLBuffer from;
if (!sel.isReadOnly())
sel.addJoinClassConditions();
sel.addJoinClassConditions();
if (sel.getFromSelect() != null)
from = getFromSelect(sel, false);
else
@ -2287,7 +2283,7 @@ public class DBDictionary
if (join.isCorrelated() && join.getForeignKey() != null) {
SQLBuffer where = new SQLBuffer(this);
where.append("(").append(toTraditionalJoin(join)).append(")");
sel.where(where);
sel.where(where.getSQL());
}
}
}
@ -2347,7 +2343,7 @@ public class DBDictionary
if (join.getForeignKey() != null){
SQLBuffer where = new SQLBuffer(this);
where.append("(").append(toTraditionalJoin(join)).append(")");
sel.where(where);
sel.where(where.getSQL());
}
break;
}
@ -2497,7 +2493,7 @@ public class DBDictionary
if (join.getForeignKey() != null){
SQLBuffer where = new SQLBuffer(this);
where.append("(").append(toTraditionalJoin(join)).append(")");
sel.where(where);
sel.where(where.getSQL());
}
return null;

View File

@ -39,9 +39,9 @@ class JoinSet {
// efficient representation with O(1) lookup, add, remove operations for
// typical sets of joins, and it means we'd have to create a graph anyway
// when joinIterator() is called
private final List<Node> _graph = new ArrayList<Node>();
private final List _graph = new ArrayList();
private int _size = 0;
private List<Join> _sorted = null;
private List _sorted = null;
public JoinSet() {
}
@ -51,7 +51,7 @@ class JoinSet {
if (copy._graph.get(i) == null)
_graph.add(null);
else
_graph.add((Node) copy._graph.get(i).clone());
_graph.add(((Node) copy._graph.get(i)).clone());
}
_size = copy._size;
_sorted = copy._sorted;
@ -95,22 +95,23 @@ class JoinSet {
/**
* Iterator over joins that prepares them for SQL translation.
*/
public Iterator<Join> joinIterator() {
public Iterator joinIterator() {
if (_size < 2)
return iterator();
if (_sorted != null)
return _sorted.iterator();
List<Join> sorted = new ArrayList<Join>(_size);
LinkedList<Node> queue = new LinkedList<Node>();
BitSet seen = new BitSet(_graph.size() * _graph.size() + _graph.size());
List sorted = new ArrayList(_size);
LinkedList queue = new LinkedList();
BitSet seen = new BitSet(_graph.size() * _graph.size()
+ _graph.size());
// traverse graph
Node n;
int idx, sidx;
for (int i = 0; i < _graph.size(); i++) {
// seed queue with next set of disconnected joins
for (n = _graph.get(i); n != null; n = n.next) {
for (n = (Node) _graph.get(i); n != null; n = n.next) {
sidx = getSeenIndex(n.join);
if (!seen.get(sidx)) {
seen.set(sidx);
@ -182,8 +183,8 @@ class JoinSet {
return false;
boolean added = false;
for (Iterator<Join> itr = js.iterator(); itr.hasNext();)
added = add(itr.next()) || added;
for (Iterator itr = js.iterator(); itr.hasNext();)
added = add((Join) itr.next()) || added;
return added;
}
@ -217,8 +218,8 @@ class JoinSet {
_size++;
}
public Iterator<Join> iterator() {
return new Iterator<Join>() {
public Iterator iterator() {
return new Iterator() {
private Node _next = null;
private int _idx = -1;
@ -236,7 +237,7 @@ class JoinSet {
return false;
}
public Join next() {
public Object next() {
if (!hasNext())
throw new NoSuchElementException();
Join j = _next.join;
@ -288,16 +289,16 @@ class JoinSet {
public boolean removeAll(JoinSet js) {
boolean remd = false;
for (Iterator<Join> itr = js.iterator(); itr.hasNext();)
remd = remove(itr.next()) || remd;
for (Iterator itr = js.iterator(); itr.hasNext();)
remd = remove((Join) itr.next()) || remd;
return remd;
}
public boolean retainAll(JoinSet js) {
boolean remd = false;
Join join;
for (Iterator<Join> itr = iterator(); itr.hasNext();) {
join = itr.next();
for (Iterator itr = iterator(); itr.hasNext();) {
join = (Join) itr.next();
if (!js.contains(join))
remd = remove(join);
}
@ -317,8 +318,8 @@ class JoinSet {
public boolean containsAll(JoinSet js) {
if (js._size > _size || js._graph.size() > _graph.size())
return false;
for (Iterator<Join> itr = js.iterator(); itr.hasNext();)
if (!contains(itr.next()))
for (Iterator itr = js.iterator(); itr.hasNext();)
if (!contains((Join) itr.next()))
return false;
return true;
}
@ -346,7 +347,7 @@ class JoinSet {
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("[");
for (Iterator<Join> itr = iterator(); itr.hasNext();) {
for (Iterator itr = iterator(); itr.hasNext();) {
buf.append("<").append(itr.next()).append(">");
if (itr.hasNext())
buf.append(", ");

View File

@ -102,10 +102,4 @@ public interface Joins {
* Move joins that belong to subquery's parent
*/
public void moveJoinsToParent();
/**
* Gets the current path as a mutable string.
* @return
*/
public StringBuilder path();
}

View File

@ -112,15 +112,6 @@ public class LogicalUnion
return false;
}
@Override
public boolean isReadOnly() {
for (int i = 0; i < sels.length; i++) {
if (sels[i].isReadOnly())
return true;
}
return false;
}
public void abortUnion() {
}
@ -244,7 +235,8 @@ public class LogicalUnion
if (getExpectedResultCount() == 1) {
AbstractResult res;
for (int i = 0; i < sels.length; i++) {
res = (AbstractResult) sels[i].execute(store, fetch, lockLevel);
res = (AbstractResult) sels[i].execute(store, fetch,
lockLevel);
res.setBaseMapping(mappings[i]);
res.setIndexOf(i);
@ -275,7 +267,8 @@ public class LogicalUnion
try {
List l;
for (int i = 0; i < res.length; i++) {
res[i] = (AbstractResult) sels[i].execute(store, fetch, lockLevel);
res[i] = (AbstractResult) sels[i].execute(store, fetch,
lockLevel);
res[i].setBaseMapping(mappings[i]);
res[i].setIndexOf(i);
@ -775,6 +768,14 @@ public class LogicalUnion
sel.where(sql, joins);
}
public void where(String sql) {
sel.where(sql);
}
public void where(String sql, Joins joins) {
sel.where(sql, joins);
}
public void having(SQLBuffer sql) {
sel.having(sql);
}
@ -783,6 +784,14 @@ public class LogicalUnion
sel.having(sql, joins);
}
public void having(String sql) {
sel.having(sql);
}
public void having(String sql, Joins joins) {
sel.having(sql, joins);
}
public void groupBy(SQLBuffer sql) {
sel.groupBy(sql);
}
@ -922,10 +931,6 @@ public class LogicalUnion
public DBDictionary getDictionary() {
return dict;
}
public boolean isReadOnly() {
return sel.isReadOnly();
}
}
/**
@ -1006,5 +1011,4 @@ public class LogicalUnion
return a1.length - a2.length;
}
}
}

View File

@ -32,6 +32,7 @@ import java.util.List;
import org.apache.commons.lang.ObjectUtils;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.exps.CollectionParam;
import org.apache.openjpa.jdbc.kernel.exps.Val;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.Sequence;
@ -52,7 +53,6 @@ import org.apache.openjpa.kernel.exps.Parameter;
*
* @since 0.2.4
*/
@SuppressWarnings("serial")
public final class SQLBuffer
implements Serializable, Cloneable {
@ -60,8 +60,14 @@ public final class SQLBuffer
private final DBDictionary _dict;
private final StringBuilder _sql = new StringBuilder();
private List<Subselect> _subsels = null;
private List<BindParameter> _params = null;
private List _subsels = null;
private List _params = null;
private List _cols = null;
// Even element refers to an index of the _params list
// Odd element refers to the user parameter
private List _userIndex = null;
private List _userParams = null;
/**
* Default constructor.
@ -86,7 +92,7 @@ public final class SQLBuffer
}
/**
* Return true if the buffer is empty.
* Return true if the buffer is emtpy.
*/
public boolean isEmpty() {
return _sql.length() == 0;
@ -96,42 +102,87 @@ public final class SQLBuffer
* Append all SQL and parameters of the given buffer.
*/
public SQLBuffer append(SQLBuffer buf) {
append(buf, _sql.length(), (_params == null) ? 0 : _params.size(), true);
append(buf, _sql.length(), (_params == null) ? 0 : _params.size(),
true);
return this;
}
/**
* Append all SQL and parameters of the given buffer at the given positions.
*/
private void append(SQLBuffer buf, int sqlIndex, int paramIndex, boolean subsels) {
private void append(SQLBuffer buf, int sqlIndex, int paramIndex,
boolean subsels) {
if (subsels) {
// only allow appending of buffers with subselects, not insertion
if (_subsels != null && !_subsels.isEmpty() && sqlIndex != _sql.length())
if (_subsels != null && !_subsels.isEmpty()
&& sqlIndex != _sql.length())
throw new IllegalStateException();
if (buf._subsels != null && !buf._subsels.isEmpty()) {
if (sqlIndex != _sql.length())
throw new IllegalStateException();
if (_subsels == null)
_subsels = new ArrayList<Subselect>(buf._subsels.size());
_subsels = new ArrayList(buf._subsels.size());
for (int i = 0; i < buf._subsels.size(); i++)
_subsels.add((buf._subsels.get(i)).clone(sqlIndex, paramIndex));
_subsels.add(((Subselect) buf._subsels.get(i)).
clone(sqlIndex, paramIndex));
}
}
if (sqlIndex == _sql.length()) {
if (sqlIndex == _sql.length())
_sql.append(buf._sql.toString());
} else {
else
_sql.insert(sqlIndex, buf._sql.toString());
}
if (buf._params != null) {
if (_params == null)
_params = new ArrayList<BindParameter>();
_params = new ArrayList();
if (_cols == null && buf._cols != null) {
_cols = new ArrayList();
while (_cols.size() < _params.size())
_cols.add(null);
}
if (paramIndex == _params.size()) {
_params.addAll(buf._params);
if (buf._userParams != null) {
if (_userParams == null)
_userParams = new ArrayList();
_userParams.addAll(paramIndex, buf._userParams);
}
if (buf._userIndex != null) {
if (_userIndex == null)
_userIndex = new ArrayList();
_userIndex.addAll(buf._userIndex);
}
if (buf._cols != null)
_cols.addAll(buf._cols);
else if (_cols != null)
while (_cols.size() < _params.size())
_cols.add(null);
} else {
_params.addAll(paramIndex, buf._params);
if ( buf._userParams != null) {
if (_userParams == null)
_userParams = new ArrayList();
_userParams.addAll(paramIndex, buf._userParams);
}
if (buf._userIndex != null) {
if (_userIndex == null)
_userIndex = new ArrayList();
_userIndex.addAll(buf._userIndex);
}
if (buf._cols != null)
_cols.addAll(paramIndex, buf._cols);
else if (_cols != null)
while (_cols.size() < _params.size())
_cols.add(paramIndex, null);
}
}
if (_userIndex != null) {
// fix up user parameter index
for (int i = 0; i < _userIndex.size(); i+=2) {
_userIndex.set(i, _userParams.indexOf(_userIndex.get(i+1)));
}
}
}
@ -190,7 +241,7 @@ public final class SQLBuffer
_sql.append(")");
if (_subsels == null)
_subsels = new ArrayList<Subselect>(2);
_subsels = new ArrayList(2);
_subsels.add(sub);
return this;
}
@ -216,7 +267,7 @@ public final class SQLBuffer
* Append a parameter value.
*/
public SQLBuffer appendValue(Object o) {
return appendValue(o, null, null);
return appendValue(o, null);
}
/**
@ -242,11 +293,34 @@ public final class SQLBuffer
else {
_sql.append(PARAMETER_TOKEN);
// initialize param and col lists; we hold off on col list until
// we get the first non-null col
if (_params == null)
_params = new ArrayList<BindParameter>();
BindParameter param = new BindParameter(userParam == null ? col : userParam,
userParam != null, col, o);
_params.add(param);
_params = new ArrayList();
if (_userParams == null)
_userParams = new ArrayList();
if (col != null && _cols == null) {
_cols = new ArrayList();
while (_cols.size() < _params.size())
_cols.add(null);
}
_params.add(o);
if (userParam != null) {
Object param = userParam;
if (userParam instanceof CollectionParam)
param = ((CollectionParam) userParam).clone();
_userParams.add(param);
if (_userIndex == null)
_userIndex = new ArrayList();
int index = _params.size()-1;
_userIndex.add(index);
_userIndex.add(param);
}
else
_userParams.add(o);
if (_cols != null)
_cols.add(col);
}
return this;
}
@ -254,9 +328,8 @@ public final class SQLBuffer
/**
* Return the list of parameter values.
*/
public List<BindParameter> getParameters() {
if (_params == null) return Collections.emptyList();
return _params;
public List getParameters() {
return (_params == null) ? Collections.EMPTY_LIST : _params;
}
/**
@ -267,33 +340,10 @@ public final class SQLBuffer
* This structure is preferred over a normal map because a user parameter
* may occur more than one in the parameters.
*/
public List<Object> getUserParameters() {
if (_params == null)
return Collections.emptyList();
List<Object> userParam = new ArrayList<Object>();
for (int i = 0; i < _params.size(); i++) {
BindParameter param = _params.get(i);
if (param.isUser()) {
userParam.add(i);
userParam.add(param.getKey());
}
}
return userParam;
}
/**
* Gets the columns associated with the binding parameters.
* All binding parameter may not have an associated column.
*/
public List<Column> getColumns() {
if (_params == null)
return Collections.emptyList();
List<Column> columns = new ArrayList<Column>();
for (BindParameter param : _params) {
columns.add(param.getColumn());
}
return columns;
public List getUserParameters() {
if (_userIndex == null)
return Collections.EMPTY_LIST;
return _userIndex;
}
/**
@ -316,14 +366,14 @@ public final class SQLBuffer
return sql;
StringBuilder buf = new StringBuilder();
Iterator<BindParameter> pi = _params.iterator();
Iterator pi = _params.iterator();
for (int i = 0; i < sql.length(); i++) {
if (sql.charAt(i) != '?') {
buf.append(sql.charAt(i));
continue;
}
Object param = pi.hasNext() ? pi.next().getValue() : null;
Object param = pi.hasNext() ? pi.next() : null;
if (param == null)
buf.append("NULL");
else if (param instanceof Number || param instanceof Boolean)
@ -380,7 +430,7 @@ public final class SQLBuffer
}
/**
* Create and populate the parameters of a prepared statement using the
* Create and populate the parameters of a prepred statement using the
* SQL in this buffer and the given fetch configuration.
*/
public PreparedStatement prepareStatement(Connection conn,
@ -488,9 +538,10 @@ public final class SQLBuffer
if (_params == null)
return;
Column col;
for (int i = 0; i < _params.size(); i++) {
BindParameter param = _params.get(i);
_dict.setUnknown(ps, i + 1, param.getValue(), param.getColumn());
col = (_cols == null) ? null : (Column) _cols.get(i);
_dict.setUnknown(ps, i + 1, _params.get(i), col);
}
}
@ -567,42 +618,11 @@ public final class SQLBuffer
}
}
/**
* Sets the binding parameters, clearing all existing parameters.
*
* @param params a non-null list of parameters.
*/
public void setParameters(List<?> params) {
if (params == null) {
throw new IllegalArgumentException("Can not set null parameter");
}
_params = new ArrayList<BindParameter>();
int i = 0;
for (Object p : params) {
BindParameter param = new BindParameter(i, false, null, p);
_params.add(param);
}
public void setParameters(List params) {
_params = params;
}
/**
* Binds the given value to a parameter representing the given column.
* The column must be bound before this call.
* @param o a parameter value
* @param col a column to which the value is to be bound
* @return this same buffer
* @exception IllegalArgumentException is no parameter represents the given column
*/
public SQLBuffer bind(Object o, Column col) {
boolean bound = false;
for (int i = 0; i < _params.size(); i++) {
BindParameter param = _params.get(i);
if (param.getColumn() == col) {
param.setValue(o);
bound = true;
}
}
if (!bound)
throw new IllegalArgumentException("Column " + col + " does not exist to bind " + o);
return this;
public List getColumns() {
return _cols;
}
}

View File

@ -546,12 +546,12 @@ public interface Select
/**
* Add the given where conditions.
*/
// public void where(String sql);
public void where(String sql);
/**
* Add the given where conditions.
*/
// public void where(String sql, Joins joins);
public void where(String sql, Joins joins);
/**
* Add the given having conditions.
@ -566,12 +566,12 @@ public interface Select
/**
* Add the given having conditions.
*/
// public void having(String sql);
public void having(String sql);
/**
* Add the given having conditions.
*/
// public void having(String sql, Joins joins);
public void having(String sql, Joins joins);
/**
* Group by the given column.
@ -606,12 +606,12 @@ public interface Select
/**
* Add a GROUP BY clause.
*/
// public void groupBy(String sql);
public void groupBy(String sql);
/**
* Add a GROUP BY clause.
*/
// public void groupBy(String sql, Joins joins);
public void groupBy(String sql, Joins joins);
/**
* Group by the columns of the given mapping, possibly including subclasses.
@ -751,29 +751,22 @@ public interface Select
/**
* Set joined table metadatas for polymorphic queries
*/
public void setJoinedTableClassMeta(List<ClassMapping> meta);
public void setJoinedTableClassMeta(List meta);
/**
* get joined table metadatas for polymorphic queries
*/
public List<ClassMapping> getJoinedTableClassMeta();
public List getJoinedTableClassMeta();
/**
* Set joined table metadatas excluded for polymorphic queries
*/
public void setExcludedJoinedTableClassMeta(List<ClassMapping> meta);
public void setExcludedJoinedTableClassMeta(List meta);
/**
* get joined table metadatas excluded for polymorphic queries
*/
public List<ClassMapping> getExcludedJoinedTableClassMeta();
public List getExcludedJoinedTableClassMeta();
/**
* Gets the database dictionary used by this select to form the target SQL
* statement.
*
* @return the immutable database dictionary.
*/
public DBDictionary getDictionary() ;
}

View File

@ -23,7 +23,6 @@ import java.sql.SQLException;
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.schema.Column;
/**
* Interface for configuring and executing a SQL select.
@ -152,19 +151,4 @@ public interface SelectExecutor {
* @since 2.0.0
*/
public boolean hasMultipleSelects();
/**
* Affirms if this select is structurally immutable.
* A select becomes immutable upon {@link #execute(JDBCStore, JDBCFetchConfiguration) execution}.
* There is no explicit way to turn a select into read-only status.
* <br>
* The immutable contract does not prevent {@link SQLBuffer#bind(Object, Column) binding}
* new values to {@link BindParameter parameters}.
*
* @return false on construction, true after execution.
*
* @since 2.2.0
*/
boolean isReadOnly();
}

View File

@ -271,14 +271,11 @@ public class DelegatingQuery
}
}
public void setCandidateType(Class<?> cls, boolean subs) {
public void setCandidateType(Class cls, boolean subs) {
try {
lock();
_query.setCandidateType(cls, subs);
} catch (RuntimeException re) {
throw translate(re);
} finally {
unlock();
}
}
@ -292,12 +289,9 @@ public class DelegatingQuery
public void setReadOnly(boolean readOnly) {
try {
lock();
_query.setReadOnly(readOnly);
} catch (RuntimeException re) {
throw translate(re);
} finally {
unlock();
}
}

View File

@ -27,20 +27,19 @@ 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;
}
@ -48,8 +47,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) {
@ -60,8 +59,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)
@ -90,7 +89,7 @@ public class InheritanceComparator
/**
* Count the levels of inheritance between this class and our base class.
*/
private int levels(Class<?> to) {
private int levels(Class to) {
if (to.isInterface())
return to.getInterfaces().length;
for (int i = 0; to != null; i++, to = to.getSuperclass())

View File

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

View File

@ -106,7 +106,8 @@ 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<?>>());
@ -123,8 +124,7 @@ 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<?>, Collection<Class<?>>> _subs =
Collections.synchronizedMap(new HashMap<Class<?>, Collection<Class<?>>>());
private Map<Class<?>, List<Class<?>>> _subs = Collections.synchronizedMap(new HashMap<Class<?>, List<Class<?>>>());
// xml mapping
protected final XMLMetaData[] EMPTY_XMLMETAS;
@ -283,7 +283,7 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
}
/**
* Affirms if this repository will load all known persistent classes at initialization.
* Sets whether 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) {
if (_preload == false) {
return;
}
// If pooling EMFs, this method may be invoked more than once. Only perform this work once.
if (_preloadComplete) {
if (_preloadComplete == true) {
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,7 +359,8 @@ 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;
@ -855,8 +856,9 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
}
private ClassMetaData[] getMetaDatasInternal() {
// prevent concurrent modification errors when resolving one metadata introduces others
ClassMetaData[] metas = _metas.values().toArray(new ClassMetaData[_metas.size()]);
// prevent concurrent mod errors when resolving one metadata
// introduces others
ClassMetaData[] metas = (ClassMetaData[]) _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);
@ -1798,8 +1800,7 @@ 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<Class<?>, Collection<Class<?>>> map, Class<?> key, Class<?> value,
boolean inheritance) {
private void addToCollection(Map map, Class<?> key, Class<?> value, boolean inheritance) {
if (_locking) {
synchronized (map) {
addToCollectionInternal(map, key, value, inheritance);
@ -1809,17 +1810,15 @@ public class MetaDataRepository implements PCRegistry.RegisterClassListener, Con
}
}
private void addToCollectionInternal(Map<Class<?>, Collection<Class<?>>> map, Class<?> key,
Class<?> value, boolean inheritance) {
Collection<Class<?>> coll = map.get(key);
private void addToCollectionInternal(Map map, Class<?> key, Class<?> value, boolean inheritance) {
Collection coll = (Collection) 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);
@ -1893,7 +1892,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<?>, Collection<Class<?>>>();
_subs = new HashMap<Class<?>, List<Class<?>>>();
// Wait till we're done loading MetaData to flip _lock boolean.
}
}

View File

@ -58,11 +58,11 @@ import org.apache.openjpa.conf.OpenJPAConfiguration;
public class ImplHelper {
// Cache for from/to type assignments
private static final Map<Class<?>,Map<?,?>> _assignableTypes =
private static final Map _assignableTypes =
new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD);
// map of all new unenhanced instances active in this classloader
public static final Map<Object,PersistenceCapable> _unenhancedInstanceMap =
public static final Map _unenhancedInstanceMap =
new ConcurrentReferenceHashMap(ReferenceMap.WEAK, ReferenceMap.HARD) {
protected boolean eq(Object x, Object y) {
@ -91,13 +91,13 @@ public class ImplHelper {
* @see StoreManager#loadAll
* @since 0.4.0
*/
public static Collection<Object> loadAll(Collection<OpenJPAStateManager> sms, StoreManager store,
public static Collection loadAll(Collection sms, StoreManager store,
PCState state, int load, FetchConfiguration fetch, Object context) {
Collection<Object> failed = null;
Collection failed = null;
OpenJPAStateManager sm;
LockManager lm;
for (Iterator<OpenJPAStateManager> itr = sms.iterator(); itr.hasNext();) {
sm = itr.next();
for (Iterator itr = sms.iterator(); itr.hasNext();) {
sm = (OpenJPAStateManager) itr.next();
if (sm.getManagedInstance() == null) {
if (!store.initialize(sm, state, fetch, context))
failed = addFailedId(sm, failed);
@ -110,23 +110,23 @@ public class ImplHelper {
} else if (!store.exists(sm, context))
failed = addFailedId(sm, failed);
}
if (failed == null) return Collections.emptyList();
return failed;
return (failed == null) ? Collections.EMPTY_LIST : failed;
}
/**
* Add identity of given instance to collection.
*/
private static Collection<Object> addFailedId(OpenJPAStateManager sm, Collection<Object> failed) {
private static Collection addFailedId(OpenJPAStateManager sm,
Collection failed) {
if (failed == null)
failed = new ArrayList<Object>();
failed = new ArrayList();
failed.add(sm.getId());
return failed;
}
/**
* Generate a value for the given metadata, or return null. Generates
* values for the following strategies: {@link ValueStrategies#SEQUENCE},
* values for hte following strategies: {@link ValueStrategies#SEQUENCE},
* {@link ValueStrategies#UUID_STRING}, {@link ValueStrategies#UUID_HEX}
*/
public static Object generateIdentityValue(StoreContext ctx,
@ -136,7 +136,7 @@ public class ImplHelper {
/**
* Generate a value for the given metadata, or return null. Generates
* values for the following strategies: {@link ValueStrategies#SEQUENCE},
* values for hte following strategies: {@link ValueStrategies#SEQUENCE},
* {@link ValueStrategies#UUID_STRING}, {@link ValueStrategies#UUID_HEX}
*/
public static Object generateFieldValue(StoreContext ctx,
@ -218,9 +218,11 @@ public class ImplHelper {
*
* @since 1.0.0
*/
public static boolean isManagedType(OpenJPAConfiguration conf, Class<?> type) {
return (type != null && PersistenceCapable.class.isAssignableFrom(type)
|| ((conf == null || conf.getRuntimeUnenhancedClassesConstant()== RuntimeUnenhancedClassesModes.SUPPORTED)
public static boolean isManagedType(OpenJPAConfiguration conf, Class type) {
return (PersistenceCapable.class.isAssignableFrom(type)
|| (type != null
&& (conf == null || conf.getRuntimeUnenhancedClassesConstant()
== RuntimeUnenhancedClassesModes.SUPPORTED)
&& PCRegistry.isRegistered(type)));
}
@ -244,7 +246,7 @@ public class ImplHelper {
* @param to second class instance to be checked for assignability
* @return true if the "to" class is assignable to the "from" class
*/
public static boolean isAssignable(Class<?> from, Class<?> to) {
public static boolean isAssignable(Class from, Class to) {
if (from == null || to == null)
return false;
@ -306,7 +308,8 @@ public class ImplHelper {
}
}
public static void registerPersistenceCapable(ReflectingPersistenceCapable pc) {
public static void registerPersistenceCapable(
ReflectingPersistenceCapable pc) {
_unenhancedInstanceMap.put(pc.getManagedInstance(), pc);
}

View File

@ -1,51 +0,0 @@
/*
* 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 ImmutableBooleanValue(String prop, boolean value) {
super(prop);
set(value);
}
public void set(boolean value) {
if (_dirty) {
if (value != get().booleanValue())
throw new IllegalStateException(this + " can not be changed from " + get() + " to " + value);
} else {
_dirty = true;
super.set(value);
}
}
}

View File

@ -1,89 +0,0 @@
/*
* 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.util;
import java.util.Map;
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashMap;
/**
* A thread-specific storage similar to {@link ThreadLocal} that
* <em>heuristically</em> relaxes the affinity of a value to a thread.
* <br>
* A thread <tt>t1</tt> can {@linkplain #set(Object) set} a value, while
* a different thread <tt>t2</tt> can {@linkplain #get() access} the same
* value, if <tt>t1</tt> and <tt>t2</tt> are <em>{@link #eq(Object, Object)
* equivalent}</em>.
*
* @author Pinaki Poddar
* @since 2.2.0
*/
public class FlexibleThreadLocal extends ConcurrentReferenceHashMap {
/**
* Must not hold hard reference to the threads used as keys.
*/
public FlexibleThreadLocal() {
super(ReferenceMap.WEAK, ReferenceMap.HARD);
}
/**
* Gets the value associated with the calling thread or its equivalent.
*
* @see #eq(Object, Object)
*/
public Object get() {
Thread current = Thread.currentThread();
if (containsKey(current)) {
return super.get(current);
} else {
if (size() == 1)
return ((Map.Entry)entrySet().iterator().next()).getValue();
throw new RuntimeException(current + " is not a known thread. Known threads are " + keySet());
}
}
/**
* Associates the value to the current thread.
*/
public void set(Object t) {
super.put(Thread.currentThread(), t);
}
/**
* Affirms if the two given thread are equivalent.
* Two threads are equivalent if the they are identical (of course),
* or they belong to the same thread group or they are <em>equal</em>.
* The equality can be defined <em>asymmetrically</em> by the
* thread implementation. For example, a child thread (as done in Slice)
* can equal its parent thread which is a native thread. But the parent
* (native) thread is not equal to the child thread.
*/
@Override
protected boolean eq(Object a, Object b) {
if (a == b) return true;
if (a == null || b == null) return false;
if (a instanceof Thread && b instanceof Thread)
if (((Thread)a).getThreadGroup() == ((Thread)b).getThreadGroup())
return true;
return a.equals(b) || b.equals(a);
}
}

View File

@ -1,60 +0,0 @@
/*
* 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.util;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
/**
* A thread gate that guards on first invocation and remains open after the first invocation.
* Used when a structure (such as Select) is constructed and populated first-time in a
* thread-safe manner and can be used later with minimal thread synchronization overhead.
*
* @author Pinaki Poddar
*
*/
@SuppressWarnings("serial")
public class ThreadGate extends ReentrantLock {
private AtomicBoolean _once = new AtomicBoolean(false);
/**
* Lock the gate only if it has never been locked.
*/
@Override
public void lock() {
synchronized (_once) {
if (!_once.get()) {
super.lock();
}
}
}
/**
* Unlock the gate and keep it open for ever.
*/
@Override
public void unlock() {
if (_once.compareAndSet(false, true)) {
super.unlock();
synchronized (_once) {
_once.notifyAll();
}
}
}
}

View File

@ -1,110 +0,0 @@
/*
* 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 agEmployee_Last_Name 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.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
import junit.framework.TestCase;
public class TestFlexibleThreadLocal extends TestCase {
private static final int MAX_THREAD = 10;
public void testCorrectValuesAreRetrievedWhenThreadsAreInSameGroup() throws Exception {
ExecutorService threadPool = Executors.newCachedThreadPool();
List<Future<?>> futures = new ArrayList<Future<?>>();
for (int i = 0; i < MAX_THREAD; i++) {
Future<?> f = threadPool.submit(new User());
futures.add(f);
}
waitForTermination(futures);
threadPool.shutdown();
threadPool.awaitTermination(10, TimeUnit.SECONDS);
}
public void testCorrectValuesAreRetrievedWhenThreadsAreNotInSameGroup() throws Exception {
Thread[] threads = new Thread[MAX_THREAD];
for (int i = 0; i < MAX_THREAD; i++) {
threads[i] = new Thread(new User());
threads[i].start();
}
waitForTermination(threads);
}
void waitForTermination(Thread[] threads) {
for (int i = 0; i < MAX_THREAD; i++) {
try {
threads[i].join();
threads[i].interrupt();
} catch (Exception e) {
e.printStackTrace();
fail(e.toString());
}
}
}
void waitForTermination(List<Future<?>> futures) {
for (Future<?> f : futures) {
try {
f.get();
} catch (Exception e) {
e.printStackTrace();
fail(e.toString());
}
}
}
}
/**
* Sets and gets random values in a flexible thread local.
*
*/
class User implements Runnable {
private static final Random _rng = new Random();
Integer[] randoms = new Integer[20];
static final FlexibleThreadLocal test = new FlexibleThreadLocal();
public User() {
for (int i = 0; i < randoms.length; i++) {
randoms[i] = _rng.nextInt();
}
}
@Override
public void run() {
for (int i = 0; i < randoms.length; i++) {
test.set(randoms[i]);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Assert.assertEquals(Thread.currentThread() + " item " + i, randoms[i], test.get());
}
}
}

View File

@ -1,161 +0,0 @@
/*
* 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.util;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import junit.framework.TestCase;
import org.apache.openjpa.lib.util.ThreadGate;
/**
* Tests a thread gate.
*
* @author Pinaki Poddar
*
*/
public class TestGate extends TestCase {
public static enum Op {ENTER, EXIT};
public static int MAX_THREAD = 4;
public static int THREAD_TIME = 10;
private ExecutorService threadPool;
public void testAllThreadsBlockUntilFirstAccessIsComplete() throws Exception {
for (int i = 0; i < 100; i++) {
threadPool = Executors.newFixedThreadPool(MAX_THREAD);
allThreadsBlockUntilFirstAccessIsComplete();
}
}
public void allThreadsBlockUntilFirstAccessIsComplete() throws Exception {
final Info info = new Info();
final ThreadGate gate = new ThreadGate();
final AtomicBoolean first = new AtomicBoolean(true);
List<Future<?>> futures = new ArrayList<Future<?>>();
for (int i = 0; i < MAX_THREAD; i++) {
Runnable r = new Runnable() {
@Override
public void run() {
gate.lock();
try {
info.enter();
Thread.sleep(THREAD_TIME);
info.exit();
} catch (InterruptedException e) {
fail();
} finally {
gate.unlock();
}
}
};
futures.add(threadPool.submit(r));
}
for (Future<?> f : futures) {
try {
f.get();
assertTrue(f.isDone());
assertFalse(f.isCancelled());
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
// assertEquals(2*MAX_THREAD, info.msg.size());
Token enter = info.msg.get(0);
Token exit = info.msg.get(1);
assertEquals(Op.ENTER, enter.op);
assertEquals(Op.EXIT, exit.op);
assertSame(enter.thread, exit.thread);
for (int i = 2; i < info.msg.size(); i++) {
Token token = info.msg.get(i);
if (token.op == Op.ENTER) {
Token pair = info.find(i+1, token);
assertNotNull("No pair for " + token.thread, pair);
}
}
}
/**
* Records starting and stopping of threads.
*
*/
public class Info {
Vector<Token> msg = new Vector<Token>();
/**
* Record entry of the current thread.
*/
public void enter() {
msg.add(new Token(Thread.currentThread(), Op.ENTER));
}
/**
* Record exit of the current thread.
*/
public void exit() {
msg.add(new Token(Thread.currentThread(), Op.EXIT));
}
/**
* Find the exit record corresponding to a given entry record.
*/
public Token find(int start, Token t) {
for (int i = start; i < msg.size(); i++) {
if (msg.get(i).thread.getName().equals(t.thread.getName()))
return msg.get(i);
}
return null;
}
public void print(PrintStream out) {
for (Token t : msg) {
out.println(t);
}
}
}
/**
* Info about a thread activity.
*/
public class Token {
final Thread thread;
final Op op;
final long time;
public Token(Thread t, Op op) {
super();
this.thread = t;
this.op = op;
this.time = System.currentTimeMillis();
}
public String toString() {
return time + " " + op + " " + thread.getName();
}
}
}

View File

@ -1,86 +0,0 @@
/*
* 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.util;
import org.apache.openjpa.lib.conf.ImmutableBooleanValue;
import junit.framework.TestCase;
/**
* Tests behavior of immutable boolean value.
*
* @author Pinaki Poddar
*
*/
public class TestImmutableValue extends TestCase {
public void testDefaultValueIsFalse() {
ImmutableBooleanValue value = new ImmutableBooleanValue("a");
assertEquals(Boolean.FALSE, value.get());
}
public void testValueCanBeSetOnce() {
ImmutableBooleanValue value = new ImmutableBooleanValue("a");
value.set(true);
assertEquals(Boolean.TRUE, value.get());
}
public void testSameValueCanBeSetMoreThanOnce() {
ImmutableBooleanValue value = new ImmutableBooleanValue("a");
value.set(true);
assertEquals(Boolean.TRUE, value.get());
value.set(true);
assertEquals(Boolean.TRUE, value.get());
}
public void testDifferentValueCanNotBeSetMoreThanOnce() {
ImmutableBooleanValue value = new ImmutableBooleanValue("a");
value.set(true);
assertEquals(Boolean.TRUE, value.get());
try {
value.set(false);
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
// expected exception
}
assertEquals(Boolean.TRUE, value.get());
}
public void testInitializedAsTrue() {
ImmutableBooleanValue value = new ImmutableBooleanValue("a", true);
assertEquals(Boolean.TRUE, value.get());
}
public void testInitializedAsFalse() {
ImmutableBooleanValue value = new ImmutableBooleanValue("a", false);
assertEquals(Boolean.FALSE, value.get());
}
public void testInitializedValueCanNotBeMutated() {
ImmutableBooleanValue value = new ImmutableBooleanValue("a", true);
assertEquals(Boolean.TRUE, value.get());
try {
value.set(false);
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
// expected exception
}
assertEquals(Boolean.TRUE, value.get());
}
}

View File

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

View File

@ -87,22 +87,22 @@ public interface OpenJPAQuery<X> extends TypedQuery<X> {
* Return the candidate collection, or <code>null</code> if an
* extent was specified instead of a collection.
*/
public Collection<?> getCandidateCollection();
public Collection getCandidateCollection();
/**
* Set a collection of candidates.
*/
public OpenJPAQuery<X> setCandidateCollection(Collection<?> coll);
public OpenJPAQuery<X> setCandidateCollection(Collection coll);
/**
* Query result element type.
*/
public Class<?> getResultClass();
public Class getResultClass();
/**
* Query result element type.
*/
public OpenJPAQuery<X> setResultClass(Class<?> type);
public OpenJPAQuery<X> setResultClass(Class type);
/**
* Whether subclasses are included in the query results.
@ -150,7 +150,7 @@ public interface OpenJPAQuery<X> extends TypedQuery<X> {
/**
* Set parameters.
*/
public OpenJPAQuery<X> setParameters(Map<?,?> params);
public OpenJPAQuery<X> setParameters(Map params);
/**
* Set parameters.
@ -169,7 +169,7 @@ public interface OpenJPAQuery<X> extends TypedQuery<X> {
*
* @param params the named parameter map for the query invocation
*/
public String[] getDataStoreActions(Map<?,?> params);
public String[] getDataStoreActions(Map params);
public OpenJPAQuery<X> setMaxResults(int maxResult);
@ -207,7 +207,7 @@ public interface OpenJPAQuery<X> extends TypedQuery<X> {
* Gets whether the type of user-supplied bind parameter value and the type of target persistent
* property they bind to are checked with strong or weak constraint.
*
* @return the boolean state. False by default, i.e. the type of a bind parameter value is checked
* @return the booelan state. False by default, i.e. the type of a bind parameter value is checked
* strongly against the target property type.
*/
public boolean getRelaxBindParameterTypeChecking();

View File

@ -213,14 +213,14 @@ public class QueryImpl<X> extends AbstractQuery<X> implements Serializable {
return this;
}
public Class<?> getResultClass() {
Class<?> res = _query.getResultType();
public Class getResultClass() {
Class res = _query.getResultType();
if (res != null)
return res;
return _query.getCandidateType();
}
public OpenJPAQuery<X> setResultClass(Class<?> cls) {
public OpenJPAQuery<X> setResultClass(Class cls) {
_em.assertNotCloseInvoked();
if (ImplHelper.isManagedType(_em.getConfiguration(), cls))
_query.setCandidateType(cls, true);

View File

@ -1351,29 +1351,4 @@ for a JPQL query.
</para>
</section>
<section id="ref_guide_cache_select">
<title>Select Cache</title>
<indexterm zone="ref_guide_cache_select">
<primary>caching</primary>
<secondary>Select Cache</secondary>
</indexterm>
<para>
OpenJPA generates SQL SELECT statements to fetch database records and populates the persistent entity states
from the result data. Under certain assumptions, these select statements are invariant for an entity
or its relations except that their binding parameters vary between executions. In version 2.2.0, OpenJPA
allows these select statements be reused. Such reuse avoids the cost of regenerating these statements in
every execution.
</para>
<para>
This facility can be activated by <programlisting>openjpa.jdbc.CachesSelect</programlisting> configuration
property. This property accepts boolean value of <programlisting>true</programlisting> or
<programlisting>false</programlisting>. By default, the property value is <programlisting>false</programlisting>.
The property value can be changed once and only once.
</para>
<para>
The assumption that a select statement for a persistent entity is invariant holds only if the fetch plan
is not dynamically modified. OpenJPA runtime currently makes no attempt to ensure that the assumption
is held true i.e. the application is not modifying the fetch plan dynamically.
</para>
</section>
</chapter>

View File

@ -3427,43 +3427,6 @@ levels are equivalent. Lock levels <literal>pessimistic-read</literal>,
<para>
The following properties apply exclusively to the OpenJPA JDBC back-end.
</para>
<section id="openjpa.jdbc.CachesSelect">
<title>
openjpa.jdbc.CachesSelect
</title>
<indexterm zone="openjpa.jdbc.CachesSelect">
<primary>
Select Cache
</primary>
</indexterm>
<indexterm zone="openjpa.jdbc.CachesSelect">
<primary>
caching
</primary>
<secondary>
Select Cache
</secondary>
</indexterm>
<para>
<emphasis role="bold">Property name:</emphasis>
<literal>openjpa.jdbc.CachesSelect</literal>
</para>
<para>
<emphasis role="bold">Resource adaptor config-property:</emphasis>
<literal>CachesSelect</literal>
</para>
<para>
<emphasis role="bold">Default:</emphasis> <literal>false</literal>.
</para>
<para>
<emphasis role="bold">Description:</emphasis> A plugin string (see
<xref linkend="ref_guide_conf_plugins"/>) describing the options to reuse SQL SELECT
statements generated to load persistent entity and its relations.
See <xref linkend="ref_guide_cache_select"/> for details.
</para>
</section>
<section id="openjpa.jdbc.ConnectionDecorators">
<title>
openjpa.jdbc.ConnectionDecorators

View File

@ -50,36 +50,6 @@ public class SliceThread extends Thread {
return _parent;
}
/**
* This thread equals itself (of course), its parent and any of its siblings.
* Essentially all slice threads are equal.
* <br>
* Note: this definition of equality breaks the core definition i.e. if
* <tt>P</tt> is parent thread of a slice child <tt>S</tt>, then
* <tt>S.equals(P)</tt>, but <em>not</em> <tt>P.equals(S)</tt>.
*/
@Override
public boolean equals(Object other) {
if (other == this) return true;
if (other instanceof SliceThread) {
return ((SliceThread)other)._parent == this._parent;
}
return this._parent == other;
}
/**
* Hash code of this thread is same as its parent.
*/
@Override
public int hashCode() {
return _parent.hashCode();
}
@Override
public String toString() {
return '[' + getClass().getSimpleName() + '-'+ getName() + " child of " + _parent + ']';
}
/**
* Create a cached pool of <em>slice</em> threads.
* The thread factory creates specialized threads for preferential locking treatment.

View File

@ -357,17 +357,4 @@ public class TestBasic extends SliceTestCase {
assertEquals("newslice", SlicePersistence.getSlice(newP));
}
public void testSliceThreadEqualsParentAndSiblings() {
Thread parent = new Thread();
SliceThread s1 = new SliceThread(parent, null);
SliceThread s2 = new SliceThread(parent, null);
assertEquals(s1, parent);
assertEquals(s2, parent);
assertEquals(s1, s2);
assertNotSame(parent, s1);
assertNotSame(parent, s2);
assertNotSame(s1, s2);
}
}