use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.
the class ClassTable method getExpectedIndices.
/**
* Accessor for the indices for this table. This includes both the
* user-defined indices (via MetaData), and the ones required by foreign
* keys (required by relationships).
* @param clr The ClassLoaderResolver
* @return The indices
*/
protected Set<Index> getExpectedIndices(ClassLoaderResolver clr) {
// Auto mode allows us to decide which indices are needed as well as using what is in the users MetaData
boolean autoMode = false;
if (storeMgr.getStringProperty(RDBMSPropertyNames.PROPERTY_RDBMS_CONSTRAINT_CREATE_MODE).equals("DataNucleus")) {
autoMode = true;
}
Set<Index> indices = new HashSet();
// Add on any user-required indices for the fields/properties
Set memberNumbersSet = memberMappingsMap.keySet();
Iterator iter = memberNumbersSet.iterator();
while (iter.hasNext()) {
AbstractMemberMetaData fmd = (AbstractMemberMetaData) iter.next();
JavaTypeMapping fieldMapping = memberMappingsMap.get(fmd);
if (fieldMapping instanceof EmbeddedPCMapping) {
// Add indexes for fields of this embedded PC object
EmbeddedPCMapping embMapping = (EmbeddedPCMapping) fieldMapping;
for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
IndexMetaData imd = embFieldMapping.getMemberMetaData().getIndexMetaData();
if (imd != null) {
Index index = TableUtils.getIndexForField(this, imd, embFieldMapping);
if (index != null) {
indices.add(index);
}
}
}
} else if (fieldMapping instanceof SerialisedMapping) {
// Don't index these
} else {
// Add any required index for this field
IndexMetaData imd = fmd.getIndexMetaData();
if (imd != null) {
// Index defined so add it
Index index = TableUtils.getIndexForField(this, imd, fieldMapping);
if (index != null) {
indices.add(index);
}
} else if (autoMode) {
if (fmd.getIndexed() == null) {
// Indexing not set, so add where we think it is appropriate
if (// Ignore PKs since they will be indexed anyway
!fmd.isPrimaryKey()) {
// TODO Some RDBMS create index automatically for all FK cols so we don't need to really
RelationType relationType = fmd.getRelationType(clr);
if (relationType == RelationType.ONE_TO_ONE_UNI) {
// 1-1 with FK at this side so index the FK
if (fieldMapping instanceof ReferenceMapping) {
ReferenceMapping refMapping = (ReferenceMapping) fieldMapping;
if (refMapping.getMappingStrategy() == ReferenceMapping.PER_IMPLEMENTATION_MAPPING) {
// Cols per implementation : index each of implementations
if (refMapping.getJavaTypeMapping() != null) {
int colNum = 0;
JavaTypeMapping[] implMappings = refMapping.getJavaTypeMapping();
for (int i = 0; i < implMappings.length; i++) {
int numColsInImpl = implMappings[i].getNumberOfDatastoreMappings();
Index index = new Index(this, false, null);
for (int j = 0; j < numColsInImpl; j++) {
index.setColumn(j, fieldMapping.getDatastoreMapping(colNum++).getColumn());
}
indices.add(index);
}
}
}
} else {
Index index = new Index(this, false, null);
for (int i = 0; i < fieldMapping.getNumberOfDatastoreMappings(); i++) {
index.setColumn(i, fieldMapping.getDatastoreMapping(i).getColumn());
}
indices.add(index);
}
} else if (relationType == RelationType.ONE_TO_ONE_BI && fmd.getMappedBy() == null) {
// 1-1 with FK at this side so index the FK
Index index = new Index(this, false, null);
for (int i = 0; i < fieldMapping.getNumberOfDatastoreMappings(); i++) {
index.setColumn(i, fieldMapping.getDatastoreMapping(i).getColumn());
}
indices.add(index);
} else if (relationType == RelationType.MANY_TO_ONE_BI) {
// N-1 with FK at this side so index the FK
AbstractMemberMetaData relMmd = fmd.getRelatedMemberMetaData(clr)[0];
if (relMmd.getJoinMetaData() == null && fmd.getJoinMetaData() == null) {
if (fieldMapping.getNumberOfDatastoreMappings() > 0) {
Index index = new Index(this, false, null);
for (int i = 0; i < fieldMapping.getNumberOfDatastoreMappings(); i++) {
index.setColumn(i, fieldMapping.getDatastoreMapping(i).getColumn());
}
indices.add(index);
} else {
// TODO How do we get this?
NucleusLogger.DATASTORE_SCHEMA.warn("Table " + this + " manages member " + fmd.getFullFieldName() + " which is a N-1 but there is no column for this mapping so not adding index!");
}
}
}
}
}
}
}
}
// Check if any version column needs indexing
if (versionMapping != null) {
IndexMetaData idxmd = getVersionMetaData().getIndexMetaData();
if (idxmd != null) {
Index index = new Index(this, idxmd.isUnique(), idxmd.getExtensions());
if (idxmd.getName() != null) {
index.setName(idxmd.getName());
}
int countVersionFields = versionMapping.getNumberOfDatastoreMappings();
for (int i = 0; i < countVersionFields; i++) {
index.addColumn(versionMapping.getDatastoreMapping(i).getColumn());
}
indices.add(index);
}
}
// Check if any discriminator column needs indexing
if (discriminatorMapping != null) {
DiscriminatorMetaData dismd = getDiscriminatorMetaData();
IndexMetaData idxmd = dismd.getIndexMetaData();
if (idxmd != null) {
Index index = new Index(this, idxmd.isUnique(), idxmd.getExtensions());
if (idxmd.getName() != null) {
index.setName(idxmd.getName());
}
int countDiscrimFields = discriminatorMapping.getNumberOfDatastoreMappings();
for (int i = 0; i < countDiscrimFields; i++) {
index.addColumn(discriminatorMapping.getDatastoreMapping(i).getColumn());
}
indices.add(index);
}
}
// Add on any order fields (for lists, arrays, collections) that need indexing
Set orderMappingsEntries = getExternalOrderMappings().entrySet();
Iterator orderMappingsEntriesIter = orderMappingsEntries.iterator();
while (orderMappingsEntriesIter.hasNext()) {
Map.Entry entry = (Map.Entry) orderMappingsEntriesIter.next();
AbstractMemberMetaData fmd = (AbstractMemberMetaData) entry.getKey();
JavaTypeMapping mapping = (JavaTypeMapping) entry.getValue();
OrderMetaData omd = fmd.getOrderMetaData();
if (omd != null && omd.getIndexMetaData() != null) {
Index index = getIndexForIndexMetaDataAndMapping(omd.getIndexMetaData(), mapping);
if (index != null) {
indices.add(index);
}
}
}
// Add on any user-required indices for the class(es) as a whole (subelement of <class>)
Iterator<AbstractClassMetaData> cmdIter = managedClassMetaData.iterator();
while (cmdIter.hasNext()) {
AbstractClassMetaData thisCmd = cmdIter.next();
List<IndexMetaData> classIndices = thisCmd.getIndexMetaData();
if (classIndices != null) {
for (IndexMetaData idxmd : classIndices) {
Index index = getIndexForIndexMetaData(idxmd);
if (index != null) {
indices.add(index);
}
}
}
}
if (cmd.getIdentityType() == IdentityType.APPLICATION) {
// Make sure there is no reuse of PK fields that cause a duplicate index for the PK. Remove it if required
PrimaryKey pk = getPrimaryKey();
Iterator<Index> indicesIter = indices.iterator();
while (indicesIter.hasNext()) {
Index idx = indicesIter.next();
if (idx.getColumnList().equals(pk.getColumnList())) {
NucleusLogger.DATASTORE_SCHEMA.debug("Index " + idx + " is for the same columns as the PrimaryKey so being removed from expected set of indices. PK is always indexed");
indicesIter.remove();
}
}
}
return indices;
}
use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-rdbms by datanucleus.
the class RDBMSStoreManager method getBackingStoreForField.
/**
* Accessor for the backing store for the specified member.
* Note : if we have an embedded object that is embedded into some other type and the object has a member that requires a join table (backing store), this method
* will not cater for the different places that can be embedded.
* @param clr The ClassLoaderResolver
* @param mmd metadata for the member to be persisted by this Store
* @param type instantiated type or prefered type
* @return The backing store
*/
public Store getBackingStoreForField(ClassLoaderResolver clr, AbstractMemberMetaData mmd, Class type) {
if (mmd == null || mmd.isSerialized()) {
return null;
}
Store store = backingStoreByMemberName.get(mmd.getFullFieldName());
if (store != null) {
return store;
}
synchronized (backingStoreByMemberName) {
// Just in case we synced just after someone added since our previous lookup above
store = backingStoreByMemberName.get(mmd.getFullFieldName());
if (store != null) {
return store;
}
Class expectedMappingType = null;
if (mmd.getMap() != null) {
expectedMappingType = MapMapping.class;
} else if (mmd.getArray() != null) {
expectedMappingType = ArrayMapping.class;
} else if (mmd.getCollection() != null) {
expectedMappingType = CollectionMapping.class;
} else {
expectedMappingType = PersistableMapping.class;
}
// Validate the mapping type matches the table
try {
DatastoreClass ownerTable = getDatastoreClass(mmd.getClassName(), clr);
if (ownerTable == null) {
// Class doesn't manage its own table (uses subclass-table, or superclass-table?)
AbstractClassMetaData fieldTypeCmd = getMetaDataManager().getMetaDataForClass(mmd.getClassName(), clr);
AbstractClassMetaData[] tableOwnerCmds = getClassesManagingTableForClass(fieldTypeCmd, clr);
if (tableOwnerCmds != null && tableOwnerCmds.length == 1) {
ownerTable = getDatastoreClass(tableOwnerCmds[0].getFullClassName(), clr);
}
}
if (ownerTable != null) {
JavaTypeMapping m = ownerTable.getMemberMapping(mmd);
if (!expectedMappingType.isAssignableFrom(m.getClass())) {
String requiredType = type != null ? type.getName() : mmd.getTypeName();
NucleusLogger.PERSISTENCE.warn("Member " + mmd.getFullFieldName() + " in table=" + ownerTable + " has mapping=" + m + " but expected mapping type=" + expectedMappingType);
throw new IncompatibleFieldTypeException(mmd.getFullFieldName(), requiredType, m.getType());
}
}
} catch (NoTableManagedException ntme) {
// Embedded, so just pass through
}
if (mmd.getMap() != null) {
Table datastoreTable = getTable(mmd);
if (datastoreTable == null) {
store = new FKMapStore(mmd, this, clr);
} else {
store = new JoinMapStore((MapTable) datastoreTable, clr);
}
} else if (mmd.getArray() != null) {
Table datastoreTable = getTable(mmd);
if (datastoreTable != null) {
store = new JoinArrayStore(mmd, (ArrayTable) datastoreTable, clr);
} else {
store = new FKArrayStore(mmd, this, clr);
}
} else if (mmd.getCollection() != null) {
Table datastoreTable = getTable(mmd);
if (type == null) {
// No type to base it on so create it based on the field declared type
if (datastoreTable == null) {
// We need a "FK" relation
if (Set.class.isAssignableFrom(mmd.getType())) {
store = new FKSetStore(mmd, this, clr);
} else if (List.class.isAssignableFrom(mmd.getType()) || Queue.class.isAssignableFrom(mmd.getType())) {
store = new FKListStore(mmd, this, clr);
} else if (mmd.getOrderMetaData() != null) {
// User has requested ordering
store = new FKListStore(mmd, this, clr);
} else {
store = new FKSetStore(mmd, this, clr);
}
} else {
// We need a "JoinTable" relation.
if (Set.class.isAssignableFrom(mmd.getType())) {
store = new JoinSetStore(mmd, (CollectionTable) datastoreTable, clr);
} else if (List.class.isAssignableFrom(mmd.getType()) || Queue.class.isAssignableFrom(mmd.getType())) {
store = new JoinListStore(mmd, (CollectionTable) datastoreTable, clr);
} else if (mmd.getOrderMetaData() != null) {
// User has requested ordering
store = new JoinListStore(mmd, (CollectionTable) datastoreTable, clr);
} else {
store = new JoinSetStore(mmd, (CollectionTable) datastoreTable, clr);
}
}
} else {
// Instantiated type specified, so use it to pick the associated backing store
if (datastoreTable == null) {
if (SCOUtils.isListBased(type)) {
// List required
store = new FKListStore(mmd, this, clr);
} else {
// Set required
store = new FKSetStore(mmd, this, clr);
}
} else {
if (SCOUtils.isListBased(type)) {
// List required
store = new JoinListStore(mmd, (CollectionTable) datastoreTable, clr);
} else {
// Set required
store = new JoinSetStore(mmd, (CollectionTable) datastoreTable, clr);
}
}
}
} else {
store = new JoinPersistableRelationStore(mmd, (PersistableJoinTable) getTable(mmd), clr);
}
backingStoreByMemberName.put(mmd.getFullFieldName(), store);
return store;
}
}
use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method findObjectByUnique.
/* (non-Javadoc)
* @see org.datanucleus.ExecutionContext#findObjectByUnique(java.lang.Class, java.lang.String[], java.lang.Object[])
*/
@Override
public <T> T findObjectByUnique(Class<T> cls, String[] memberNames, Object[] memberValues) {
if (cls == null || memberNames == null || memberNames.length == 0 || memberValues == null || memberValues.length == 0) {
throw new NucleusUserException(Localiser.msg("010053", cls, StringUtils.objectArrayToString(memberNames), StringUtils.objectArrayToString(memberValues)));
}
// Check class and member existence
AbstractClassMetaData cmd = getMetaDataManager().getMetaDataForClass(cls, clr);
if (cmd == null) {
throw new NucleusUserException(Localiser.msg("010052", cls.getName()));
}
for (String memberName : memberNames) {
AbstractMemberMetaData mmd = cmd.getMetaDataForMember(memberName);
if (mmd == null) {
throw new NucleusUserException("Attempt to find object using unique key of class " + cmd.getFullClassName() + " but field " + memberName + " doesnt exist!");
}
}
// Check whether this is cached against the unique key
CacheUniqueKey uniKey = new CacheUniqueKey(cls.getName(), memberNames, memberValues);
ObjectProvider op = cache.getUnique(uniKey);
if (op == null && l2CacheEnabled) {
if (NucleusLogger.CACHE.isDebugEnabled()) {
NucleusLogger.CACHE.debug(Localiser.msg("003007", uniKey));
}
// Try L2 cache
Object pc = getObjectFromLevel2CacheForUnique(uniKey);
if (pc != null) {
op = findObjectProvider(pc);
}
}
if (op != null) {
return (T) op.getObject();
}
return (T) getStoreManager().getPersistenceHandler().findObjectForUnique(this, cmd, memberNames, memberValues);
}
use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-core by datanucleus.
the class FetchGroup method getMemberNamesForCategory.
/**
* Convenience accessor to return the member names for the specified category name.
* @param categoryName Name of the category
* @return The member names
*/
private String[] getMemberNamesForCategory(String categoryName) {
AbstractClassMetaData cmd = getMetaDataForClass();
int[] memberPositions = null;
if (categoryName.equals(DEFAULT)) {
memberPositions = cmd.getDFGMemberPositions();
} else if (categoryName.equals(ALL)) {
memberPositions = cmd.getAllMemberPositions();
} else if (categoryName.equals(BASIC)) {
memberPositions = cmd.getBasicMemberPositions(nucleusCtx.getClassLoaderResolver(null));
} else if (categoryName.equals(RELATIONSHIP)) {
memberPositions = cmd.getRelationMemberPositions(nucleusCtx.getClassLoaderResolver(null));
} else if (categoryName.equals(MULTIVALUED)) {
memberPositions = cmd.getMultivaluedMemberPositions();
} else {
throw nucleusCtx.getApiAdapter().getUserExceptionForException("Category " + categoryName + " is invalid", null);
}
String[] names = new String[memberPositions.length];
for (int i = 0; i < memberPositions.length; i++) {
names[i] = cmd.getMetaDataForManagedMemberAtAbsolutePosition(memberPositions[i]).getName();
}
return names;
}
use of org.datanucleus.metadata.AbstractClassMetaData in project datanucleus-core by datanucleus.
the class PersistenceNucleusContextImpl method isClassWithIdentityCacheable.
/* (non-Javadoc)
* @see org.datanucleus.NucleusContext#isClassWithIdentityCacheable(java.lang.Object)
*/
@Override
public boolean isClassWithIdentityCacheable(Object id) {
if (id == null) {
return false;
}
if (id instanceof SCOID) {
return false;
} else if (id instanceof DatastoreUniqueLongId) {
// This doesn't have the class name so can't get metadata
return false;
}
AbstractClassMetaData cmd = null;
String className = IdentityUtils.getTargetClassNameForIdentity(id);
if (className != null) {
// "Identity" defines the class name
cmd = getMetaDataManager().getMetaDataForClass(className, getClassLoaderResolver(id.getClass().getClassLoader()));
} else {
// Application identity with user PK class, so find all using this PK and take first one
Collection<AbstractClassMetaData> cmds = getMetaDataManager().getClassMetaDataWithApplicationId(id.getClass().getName());
if (cmds != null && !cmds.isEmpty()) {
cmd = cmds.iterator().next();
}
}
return isClassCacheable(cmd);
}
Aggregations