use of org.datanucleus.metadata.KeyMetaData in project datanucleus-rdbms by datanucleus.
the class ReferenceMapping method prepareDatastoreMapping.
/**
* Convenience method to create the necessary columns to represent this reference in the datastore.
* With "per-implementation" mapping strategy will create columns for each of the possible implementations.
* With "identity"/"xcalia" will create a single column to store a reference to the implementation value.
* @param clr The ClassLoaderResolver
*/
protected void prepareDatastoreMapping(ClassLoaderResolver clr) {
if (mappingStrategy == PER_IMPLEMENTATION_MAPPING) {
// Mapping per reference implementation, so create columns for each possible implementation
if (roleForMember == FieldRole.ROLE_ARRAY_ELEMENT) {
// Creation of columns in join table for array of references
ColumnMetaData[] colmds = null;
ElementMetaData elemmd = mmd.getElementMetaData();
if (elemmd != null && elemmd.getColumnMetaData() != null && elemmd.getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
colmds = elemmd.getColumnMetaData();
}
createPerImplementationColumnsForReferenceField(false, false, false, false, roleForMember, colmds, clr);
} else if (roleForMember == FieldRole.ROLE_COLLECTION_ELEMENT) {
// Creation of columns in join table for collection of references
ColumnMetaData[] colmds = null;
AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
ElementMetaData elemmd = mmd.getElementMetaData();
if (elemmd != null && elemmd.getColumnMetaData() != null && elemmd.getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
colmds = elemmd.getColumnMetaData();
} else if (relatedMmds != null && relatedMmds[0].getJoinMetaData() != null && relatedMmds[0].getJoinMetaData().getColumnMetaData() != null && relatedMmds[0].getJoinMetaData().getColumnMetaData().length > 0) {
// Column mappings defined at other side (M-N) on <join>
colmds = relatedMmds[0].getJoinMetaData().getColumnMetaData();
}
createPerImplementationColumnsForReferenceField(false, false, false, false, roleForMember, colmds, clr);
} else if (roleForMember == FieldRole.ROLE_MAP_KEY) {
// Creation of columns in join table for map of references as keys
ColumnMetaData[] colmds = null;
KeyMetaData keymd = mmd.getKeyMetaData();
if (keymd != null && keymd.getColumnMetaData() != null && keymd.getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
colmds = keymd.getColumnMetaData();
}
createPerImplementationColumnsForReferenceField(false, false, false, false, roleForMember, colmds, clr);
} else if (roleForMember == FieldRole.ROLE_MAP_VALUE) {
// Creation of columns in join table for map of references as values
ColumnMetaData[] colmds = null;
ValueMetaData valuemd = mmd.getValueMetaData();
if (valuemd != null && valuemd.getColumnMetaData() != null && valuemd.getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
colmds = valuemd.getColumnMetaData();
}
createPerImplementationColumnsForReferenceField(false, false, false, false, roleForMember, colmds, clr);
} else {
if (mmd.getMappedBy() == null) {
// Unidirectional 1-1
boolean embedded = (mmd.isEmbedded() || mmd.getEmbeddedMetaData() != null);
createPerImplementationColumnsForReferenceField(false, true, false, embedded, roleForMember, mmd.getColumnMetaData(), clr);
} else {
// Bidirectional 1-1/N-1
AbstractClassMetaData refCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForInterface(mmd.getType(), clr);
if (refCmd != null && refCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
// TODO Is this block actually reachable ? Would we specify "inheritance" under "interface" elements?
// Find the actual tables storing the other end (can be multiple subclasses)
AbstractClassMetaData[] cmds = storeMgr.getClassesManagingTableForClass(refCmd, clr);
if (cmds != null && cmds.length > 0) {
if (cmds.length > 1) {
NucleusLogger.PERSISTENCE.warn("Field " + mmd.getFullFieldName() + " represents either a 1-1 relation, or a N-1 relation where the other end uses" + " \"subclass-table\" inheritance strategy and more than 1 subclasses with a table. " + "This is not fully supported currently");
}
} else {
// TODO Throw an exception ?
return;
}
// TODO We need a mapping for each of the possible subclass tables
/*JavaTypeMapping referenceMapping = */
storeMgr.getDatastoreClass(cmds[0].getFullClassName(), clr).getIdMapping();
} else {
String[] implTypes = MetaDataUtils.getInstance().getImplementationNamesForReferenceField(mmd, FieldRole.ROLE_FIELD, clr, storeMgr.getMetaDataManager());
for (int j = 0; j < implTypes.length; j++) {
JavaTypeMapping refMapping = storeMgr.getDatastoreClass(implTypes[j], clr).getIdMapping();
JavaTypeMapping mapping = storeMgr.getMappingManager().getMapping(clr.classForName(implTypes[j]));
mapping.setReferenceMapping(refMapping);
this.addJavaTypeMapping(mapping);
}
}
}
}
} else if (mappingStrategy == ID_MAPPING || mappingStrategy == XCALIA_MAPPING) {
// Single (String) column storing the identity of the related object
MappingManager mapMgr = storeMgr.getMappingManager();
JavaTypeMapping mapping = mapMgr.getMapping(String.class);
mapping.setMemberMetaData(mmd);
mapping.setTable(table);
mapping.setRoleForMember(roleForMember);
Column col = mapMgr.createColumn(mapping, String.class.getName(), 0);
mapMgr.createDatastoreMapping(mapping, mmd, 0, col);
this.addJavaTypeMapping(mapping);
}
}
use of org.datanucleus.metadata.KeyMetaData in project datanucleus-rdbms by datanucleus.
the class MapTable 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.
* @param clr The ClassLoaderResolver
* @return The indices
*/
@Override
protected Set getExpectedIndices(ClassLoaderResolver clr) {
Set indices = new HashSet();
// Index for FK back to owner
if (mmd.getIndexMetaData() != null) {
Index index = TableUtils.getIndexForField(this, mmd.getIndexMetaData(), ownerMapping);
if (index != null) {
indices.add(index);
}
} else if (mmd.getJoinMetaData() != null && mmd.getJoinMetaData().getIndexMetaData() != null) {
Index index = TableUtils.getIndexForField(this, mmd.getJoinMetaData().getIndexMetaData(), ownerMapping);
if (index != null) {
indices.add(index);
}
} else {
// Fallback to an index for the foreign-key to the owner
Index index = TableUtils.getIndexForField(this, null, ownerMapping);
if (index != null) {
indices.add(index);
}
}
// Index for the key FK (if required)
if (keyMapping instanceof EmbeddedKeyPCMapping) {
// Add all indices required by fields of the embedded key
EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping;
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 {
KeyMetaData keymd = mmd.getKeyMetaData();
if (keymd != null && keymd.getIndexMetaData() != null) {
IndexMetaData idxmd = mmd.getKeyMetaData().getIndexMetaData();
Index index = TableUtils.getIndexForField(this, idxmd, keyMapping);
if (index != null) {
indices.add(index);
}
} else {
// Fallback to an index for any foreign-key to the key
if (keyMapping instanceof PersistableMapping) {
Index index = TableUtils.getIndexForField(this, null, keyMapping);
if (index != null) {
indices.add(index);
}
}
}
}
// Index for the value FK (if required)
if (valueMapping instanceof EmbeddedValuePCMapping) {
// Add all indices required by fields of the embedded value
EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping;
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 {
ValueMetaData valmd = mmd.getValueMetaData();
if (valmd != null && valmd.getIndexMetaData() != null) {
IndexMetaData idxmd = mmd.getValueMetaData().getIndexMetaData();
Index index = TableUtils.getIndexForField(this, idxmd, valueMapping);
if (index != null) {
indices.add(index);
}
} else {
// Fallback to an index for any foreign-key to the value
if (valueMapping instanceof PersistableMapping) {
Index index = TableUtils.getIndexForField(this, null, valueMapping);
if (index != null) {
indices.add(index);
}
}
}
}
return indices;
}
use of org.datanucleus.metadata.KeyMetaData in project datanucleus-rdbms by datanucleus.
the class MapTable method initialize.
/**
* Method to initialise the table definition.
* @param clr The ClassLoaderResolver
*/
@Override
public void initialize(ClassLoaderResolver clr) {
assertIsUninitialized();
MapMetaData mapmd = mmd.getMap();
if (mapmd == null) {
throw new NucleusUserException(Localiser.msg("057017", mmd));
}
PrimaryKeyMetaData pkmd = (mmd.getJoinMetaData() != null ? mmd.getJoinMetaData().getPrimaryKeyMetaData() : null);
boolean pkColsSpecified = (pkmd != null && pkmd.getColumnMetaData() != null);
boolean pkRequired = requiresPrimaryKey();
// Add owner mapping
ColumnMetaData[] ownerColmd = null;
if (mmd.getJoinMetaData() != null && mmd.getJoinMetaData().getColumnMetaData() != null && mmd.getJoinMetaData().getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
// When specified at this side they use the <join> tag
ownerColmd = mmd.getJoinMetaData().getColumnMetaData();
}
ownerMapping = ColumnCreator.createColumnsForJoinTables(clr.classForName(ownerType), mmd, ownerColmd, storeMgr, this, pkRequired, false, FieldRole.ROLE_OWNER, clr, null);
if (NucleusLogger.DATASTORE.isDebugEnabled()) {
logMapping(mmd.getFullFieldName() + ".[OWNER]", ownerMapping);
}
String keyValueFieldName = (mmd.getKeyMetaData() != null ? mmd.getKeyMetaData().getMappedBy() : null);
String valueKeyFieldName = (mmd.getValueMetaData() != null ? mmd.getValueMetaData().getMappedBy() : null);
// Add key mapping
boolean keyPC = (mmd.hasMap() && mmd.getMap().keyIsPersistent());
Class keyCls = clr.classForName(mapmd.getKeyType());
if (keyValueFieldName != null && isEmbeddedValuePC()) {
// Added in value code
} else if (isSerialisedKey() || isEmbeddedKeyPC() || (isEmbeddedKey() && !keyPC) || ClassUtils.isReferenceType(keyCls)) {
// Key = PC(embedded), PC(serialised), Non-PC(serialised), Non-PC(embedded), Reference
keyMapping = storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_MAP_KEY);
if (Boolean.TRUE.equals(mmd.getContainer().allowNulls())) {
// Make all key col(s) nullable so we can store null elements
for (int i = 0; i < keyMapping.getNumberOfColumnMappings(); i++) {
Column elementCol = keyMapping.getColumnMapping(i).getColumn();
elementCol.setNullable(true);
}
}
if (NucleusLogger.DATASTORE.isDebugEnabled()) {
logMapping(mmd.getFullFieldName() + ".[KEY]", keyMapping);
}
if (valueKeyFieldName != null && isEmbeddedKeyPC()) {
// Key (PC) is embedded and value is a field of the key
EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping;
valueMapping = embMapping.getJavaTypeMapping(valueKeyFieldName);
}
} else {
// Key = PC
ColumnMetaData[] keyColmd = null;
KeyMetaData keymd = mmd.getKeyMetaData();
if (keymd != null && keymd.getColumnMetaData() != null && keymd.getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
keyColmd = keymd.getColumnMetaData();
}
keyMapping = ColumnCreator.createColumnsForJoinTables(keyCls, mmd, keyColmd, storeMgr, this, false, false, FieldRole.ROLE_MAP_KEY, clr, null);
if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
// Make all key col(s) nullable so we can store null elements
for (int i = 0; i < keyMapping.getNumberOfColumnMappings(); i++) {
Column elementCol = keyMapping.getColumnMapping(i).getColumn();
elementCol.setNullable(true);
}
}
if (NucleusLogger.DATASTORE.isDebugEnabled()) {
logMapping(mmd.getFullFieldName() + ".[KEY]", keyMapping);
}
}
// Add value mapping
boolean valuePC = (mmd.hasMap() && mmd.getMap().valueIsPersistent());
Class valueCls = clr.classForName(mapmd.getValueType());
if (valueKeyFieldName != null && isEmbeddedKeyPC()) {
// Added in key code
} else if (isSerialisedValue() || isEmbeddedValuePC() || (isEmbeddedValue() && !valuePC) || ClassUtils.isReferenceType(valueCls)) {
// Value = PC(embedded), PC(serialised), Non-PC(serialised), Non-PC(embedded), Reference
valueMapping = storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_MAP_VALUE);
if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
// Make all value col(s) nullable so we can store null elements
for (int i = 0; i < valueMapping.getNumberOfColumnMappings(); i++) {
Column elementCol = valueMapping.getColumnMapping(i).getColumn();
elementCol.setNullable(true);
}
}
if (NucleusLogger.DATASTORE.isDebugEnabled()) {
logMapping(mmd.getFullFieldName() + ".[VALUE]", valueMapping);
}
if (keyValueFieldName != null && isEmbeddedValuePC()) {
// Value (PC) is embedded and key is a field of the value
EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping;
keyMapping = embMapping.getJavaTypeMapping(keyValueFieldName);
}
} else {
// Value = PC
ColumnMetaData[] valueColmd = null;
ValueMetaData valuemd = mmd.getValueMetaData();
if (valuemd != null && valuemd.getColumnMetaData() != null && valuemd.getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
valueColmd = valuemd.getColumnMetaData();
}
valueMapping = ColumnCreator.createColumnsForJoinTables(clr.classForName(mapmd.getValueType()), mmd, valueColmd, storeMgr, this, false, true, FieldRole.ROLE_MAP_VALUE, clr, null);
if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
// Make all value col(s) nullable so we can store null elements
for (int i = 0; i < valueMapping.getNumberOfColumnMappings(); i++) {
Column elementCol = valueMapping.getColumnMapping(i).getColumn();
elementCol.setNullable(true);
}
}
if (NucleusLogger.DATASTORE.isDebugEnabled()) {
logMapping(mmd.getFullFieldName() + ".[VALUE]", valueMapping);
}
}
// Add order mapping if required
boolean orderRequired = false;
if (mmd.getOrderMetaData() != null) {
// User requested order column so add one
orderRequired = true;
} else if (requiresPrimaryKey() && !pkColsSpecified) {
// PK is required so maybe need to add an index to form the PK
if (isEmbeddedKeyPC()) {
if (mmd.hasExtension("surrogate-pk-column") && mmd.getValueForExtension("surrogate-pk-column").equalsIgnoreCase("true")) {
// Allow user to request surrogate pk column be added (for use with JPA)
orderRequired = true;
} else if (storeMgr.getApiAdapter().getName().equalsIgnoreCase("JDO") && mmd.getMap().getKeyClassMetaData(clr).getIdentityType() != IdentityType.APPLICATION) {
// Embedded key PC with datastore id so we need an index to form the PK TODO It is arguable that we can just use all embedded key fields as part of PK here always
orderRequired = true;
}
} else if (isSerialisedKey()) {
// Serialised key, so need an index to form the PK
orderRequired = true;
} else if (keyMapping instanceof ReferenceMapping) {
// ReferenceMapping, so have order if more than 1 implementation
ReferenceMapping refMapping = (ReferenceMapping) keyMapping;
if (refMapping.getJavaTypeMapping().length > 1) {
orderRequired = true;
}
} else if (!(keyMapping instanceof PersistableMapping)) {
// Non-PC, so depends if the key column can be used as part of a PK
// TODO This assumes the keyMapping has a single column but what if it is Color with 4 cols?
Column elementCol = keyMapping.getColumnMapping(0).getColumn();
if (!storeMgr.getDatastoreAdapter().isValidPrimaryKeyType(elementCol.getJdbcType())) {
// Not possible to use this Non-PC type as part of the PK
orderRequired = true;
}
}
}
if (orderRequired) {
// Order/Adapter (index) column is required (integer based)
ColumnMetaData orderColmd = null;
if (mmd.getOrderMetaData() != null && mmd.getOrderMetaData().getColumnMetaData() != null && mmd.getOrderMetaData().getColumnMetaData().length > 0) {
// Specified "order" column info
orderColmd = mmd.getOrderMetaData().getColumnMetaData()[0];
if (orderColmd.getName() == null) {
// No column name so use default
orderColmd = new ColumnMetaData(orderColmd);
DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd);
orderColmd.setName(id.getName());
}
} else {
// No column name so use default
DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd);
orderColmd = new ColumnMetaData();
orderColmd.setName(id.getName());
}
// JDO2 spec [18.5] order column is assumed to be "int"
orderMapping = storeMgr.getMappingManager().getMapping(int.class);
ColumnCreator.createIndexColumn(orderMapping, storeMgr, clr, this, orderColmd, pkRequired && !pkColsSpecified);
if (NucleusLogger.DATASTORE.isDebugEnabled()) {
logMapping(mmd.getFullFieldName() + ".[ORDER]", orderMapping);
}
}
// Define primary key of the join table (if any)
if (pkRequired) {
if (pkColsSpecified) {
// Apply the users PK specification
applyUserPrimaryKeySpecification(pkmd);
} else {
// Define PK using internal rules
if (orderRequired) {
// Order column specified so owner+order are the PK
orderMapping.getColumnMapping(0).getColumn().setPrimaryKey();
} else {
// No order column specified so owner+key are the PK
for (int i = 0; i < keyMapping.getNumberOfColumnMappings(); i++) {
keyMapping.getColumnMapping(i).getColumn().setPrimaryKey();
}
}
}
}
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled()) {
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("057023", this));
}
storeMgr.registerTableInitialized(this);
state = TABLE_STATE_INITIALIZED;
}
use of org.datanucleus.metadata.KeyMetaData in project tests by datanucleus.
the class AnnotationPlusXMLTest method testOneToManyUniMapFK.
/**
* Test of JPA 1-N unidir Map relation
*/
public void testOneToManyUniMapFK() {
NucleusContext nucleusCtx = new PersistenceNucleusContextImpl("JPA", null);
ClassLoaderResolver clr = nucleusCtx.getClassLoaderResolver(null);
MetaDataManager metaDataMgr = new JPAMetaDataManager(nucleusCtx);
PersistenceUnitMetaData pumd = getMetaDataForPersistenceUnit(nucleusCtx, "JPATest");
metaDataMgr.loadPersistenceUnit(pumd, null);
// owner side
ClassMetaData cmd1 = (ClassMetaData) metaDataMgr.getMetaDataForClass(Person.class.getName(), clr);
AbstractMemberMetaData fmd1 = cmd1.getMetaDataForMember("phoneNumbers");
assertNotNull("Department.phoneNumbers is null!", fmd1);
assertEquals("Department.phoneNumbers mapped-by is incorrect", fmd1.getMappedBy(), null);
assertEquals("Department.phoneNumbers relationType is incorrect", fmd1.getRelationType(clr), RelationType.ONE_TO_MANY_UNI);
assertEquals("Department.phoneNumbers jointable name is incorrect", fmd1.getTable(), null);
MapMetaData mmd = fmd1.getMap();
assertNotNull("Department.phoneNumbers has no Map metadata!", mmd);
KeyMetaData keymd = fmd1.getKeyMetaData();
assertNotNull("Department.phoneNumbers has no Key metadata!", keymd);
assertEquals("Department.phoneNumbers has incorrect key mapped-by", keymd.getMappedBy(), "name");
}
use of org.datanucleus.metadata.KeyMetaData in project tests by datanucleus.
the class AnnotationTest method testMapKeyInValue.
/**
* Test for use of map with using @Key, @Value.
*/
public void testMapKeyInValue() {
ClassMetaData cmd1 = (ClassMetaData) metaDataMgr.getMetaDataForClass(Person.class.getName(), clr);
String prefix = cmd1.getFullClassName() + " : ";
AbstractMemberMetaData fmd = cmd1.getMetaDataForMember("phoneNumbers");
assertNotNull(prefix + "doesnt have required field", fmd);
MapMetaData mapmd = fmd.getMap();
assertNotNull(prefix + "MapMetaData is null!", mapmd);
assertEquals(prefix + "MapMetaData keyType is incorrect", String.class.getName(), mapmd.getKeyType());
assertEquals(prefix + "MapMetaData valueType is incorrect", PhoneNumber.class.getName(), mapmd.getValueType());
JoinMetaData joinmd = fmd.getJoinMetaData();
assertNull(prefix + "field \"phoneNumbers\" has join information!", joinmd);
KeyMetaData keymd = fmd.getKeyMetaData();
assertEquals(prefix + "field \"phoneNumbers\" has incorrect key mapped-by", "name", keymd.getMappedBy());
}
Aggregations