use of org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping in project datanucleus-rdbms by datanucleus.
the class MappingManagerImpl method createDatastoreMapping.
/**
* Method to create the datastore mapping for a particular column and java type.
* If the column is specified it is linked to the created datastore mapping.
* @param mapping The java mapping
* @param column The column (can be null)
* @param javaType The java type
* @return The datastore mapping
*/
public DatastoreMapping createDatastoreMapping(JavaTypeMapping mapping, Column column, String javaType) {
Column col = column;
String jdbcType = null;
String sqlType = null;
if (col != null && col.getColumnMetaData() != null) {
// Utilise the jdbc and sql types if specified
jdbcType = col.getColumnMetaData().getJdbcTypeName();
sqlType = col.getColumnMetaData().getSqlType();
}
Class datastoreMappingClass = storeMgr.getDatastoreAdapter().getDatastoreMappingClass(javaType, jdbcType, sqlType, clr, null);
DatastoreMapping datastoreMapping = DatastoreMappingFactory.createMapping(datastoreMappingClass, mapping, storeMgr, column);
if (column != null) {
column.setDatastoreMapping(datastoreMapping);
}
return datastoreMapping;
}
use of org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping in project datanucleus-rdbms by datanucleus.
the class MappingManagerImpl method createDatastoreMapping.
/**
* Method to create the datastore mapping for a java type mapping at a particular index.
* @param mapping The java mapping
* @param mmd MetaData for the field/property
* @param index Index of the column
* @param column The column
* @return The datastore mapping
*/
public DatastoreMapping createDatastoreMapping(JavaTypeMapping mapping, AbstractMemberMetaData mmd, int index, Column column) {
Class datastoreMappingClass = null;
if (mmd.getColumnMetaData().length > 0) {
// Use "datastore-mapping-class" extension if provided
if (mmd.getColumnMetaData()[index].hasExtension("datastore-mapping-class")) {
datastoreMappingClass = clr.classForName(mmd.getColumnMetaData()[index].getValueForExtension("datastore-mapping-class"));
}
}
if (datastoreMappingClass == null) {
String javaType = mapping.getJavaTypeForDatastoreMapping(index);
String jdbcType = null;
String sqlType = null;
if (mapping.getRoleForMember() == FieldRole.ROLE_ARRAY_ELEMENT || mapping.getRoleForMember() == FieldRole.ROLE_COLLECTION_ELEMENT) {
// Element of a collection/array
ColumnMetaData[] colmds = (mmd.getElementMetaData() != null ? mmd.getElementMetaData().getColumnMetaData() : null);
if (colmds != null && colmds.length > 0) {
jdbcType = colmds[index].getJdbcTypeName();
sqlType = colmds[index].getSqlType();
}
if (mmd.getCollection() != null && mmd.getCollection().isSerializedElement()) {
javaType = ClassNameConstants.JAVA_IO_SERIALIZABLE;
}
if (mmd.getArray() != null && mmd.getArray().isSerializedElement()) {
javaType = ClassNameConstants.JAVA_IO_SERIALIZABLE;
}
} else if (mapping.getRoleForMember() == FieldRole.ROLE_MAP_KEY) {
// Key of a map
ColumnMetaData[] colmds = (mmd.getKeyMetaData() != null ? mmd.getKeyMetaData().getColumnMetaData() : null);
if (colmds != null && colmds.length > 0) {
jdbcType = colmds[index].getJdbcTypeName();
sqlType = colmds[index].getSqlType();
}
if (mmd.getMap().isSerializedKey()) {
javaType = ClassNameConstants.JAVA_IO_SERIALIZABLE;
}
} else if (mapping.getRoleForMember() == FieldRole.ROLE_MAP_VALUE) {
// Value of a map
ColumnMetaData[] colmds = (mmd.getValueMetaData() != null ? mmd.getValueMetaData().getColumnMetaData() : null);
if (colmds != null && colmds.length > 0) {
jdbcType = colmds[index].getJdbcTypeName();
sqlType = colmds[index].getSqlType();
}
if (mmd.getMap().isSerializedValue()) {
javaType = ClassNameConstants.JAVA_IO_SERIALIZABLE;
}
} else {
// Normal field
if (mmd.getColumnMetaData().length > 0) {
// Utilise the jdbc and sql types if specified
jdbcType = mmd.getColumnMetaData()[index].getJdbcTypeName();
sqlType = mmd.getColumnMetaData()[index].getSqlType();
}
// Special case where we have IDENTITY strategy and the datastore imposes a limitation on the required datastore type
ValueGenerationStrategy strategy = mmd.getValueStrategy();
if (strategy != null) {
String strategyName = strategy.toString();
if (strategy == ValueGenerationStrategy.NATIVE) {
strategyName = storeMgr.getValueGenerationStrategyForNative(mmd.getAbstractClassMetaData(), mmd.getAbsoluteFieldNumber());
}
if (strategyName != null && ValueGenerationStrategy.IDENTITY.toString().equals(strategyName)) {
Class requestedType = clr.classForName(javaType);
Class requiredType = storeMgr.getDatastoreAdapter().getAutoIncrementJavaTypeForType(requestedType);
if (requiredType != mmd.getType()) {
NucleusLogger.DATASTORE_SCHEMA.debug("Member " + mmd.getFullFieldName() + " uses IDENTITY strategy and rather than using memberType of " + mmd.getTypeName() + " for the column type, using " + requiredType + " since the datastore requires that");
}
javaType = requiredType.getName();
}
}
if (mmd.isSerialized()) {
javaType = ClassNameConstants.JAVA_IO_SERIALIZABLE;
}
}
datastoreMappingClass = storeMgr.getDatastoreAdapter().getDatastoreMappingClass(javaType, jdbcType, sqlType, clr, mmd.getFullFieldName());
}
DatastoreMapping datastoreMapping = DatastoreMappingFactory.createMapping(datastoreMappingClass, mapping, storeMgr, column);
if (column != null) {
column.setDatastoreMapping(datastoreMapping);
}
return datastoreMapping;
}
use of org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping in project datanucleus-rdbms by datanucleus.
the class EmbeddedMapping method addMappingForMember.
/**
* Method to add a mapping for the specified member to this mapping.
* @param embCmd Class that the member belongs to
* @param embMmd Member to be added
* @param embMmds The metadata defining mapping information for the members (if any)
*/
private void addMappingForMember(AbstractClassMetaData embCmd, AbstractMemberMetaData embMmd, AbstractMemberMetaData[] embMmds) {
if (emd != null && emd.getOwnerMember() != null && emd.getOwnerMember().equals(embMmd.getName())) {
// Do nothing since we don't map owner fields (since the owner is the containing object)
} else {
AbstractMemberMetaData embeddedMmd = null;
for (int j = 0; j < embMmds.length; j++) {
// Why are these even possible ? Why are they here ? Why don't they use localised messages ?
if (embMmds[j] == null) {
throw new RuntimeException("embMmds[j] is null for class=" + embCmd.toString() + " type=" + typeName);
}
AbstractMemberMetaData embMmdForMmds = embCmd.getMetaDataForMember(embMmds[j].getName());
if (embMmdForMmds != null) {
if (embMmdForMmds.getAbsoluteFieldNumber() == embMmd.getAbsoluteFieldNumber()) {
// Same as the member we are processing, so use it
embeddedMmd = embMmds[j];
}
}
}
// Add mapping
JavaTypeMapping embMmdMapping;
MappingManager mapMgr = table.getStoreManager().getMappingManager();
if (embeddedMmd != null) {
// User has provided a field definition so map with that
embMmdMapping = mapMgr.getMapping(table, embeddedMmd, clr, FieldRole.ROLE_FIELD);
} else {
// User hasn't provided a field definition so map with the classes own definition
embMmdMapping = mapMgr.getMapping(table, embMmd, clr, FieldRole.ROLE_FIELD);
}
if (embMmd.getRelationType(clr) != RelationType.NONE && embMmdMapping instanceof AbstractContainerMapping) {
// TODO Support 1-N (unidirectional) relationships and use owner object as the key in the join table
NucleusLogger.PERSISTENCE.warn("Embedded object at " + getMemberMetaData().getFullFieldName() + " has a member " + embMmd.getFullFieldName() + " that is a container. Not fully supported as part of an embedded object!");
}
// Use field number from embMmd, since the embedded mapping info doesn't have reliable field number infos
embMmdMapping.setAbsFieldNumber(embMmd.getAbsoluteFieldNumber());
this.addJavaTypeMapping(embMmdMapping);
for (int j = 0; j < embMmdMapping.getNumberOfDatastoreMappings(); j++) {
// Register column with mapping
DatastoreMapping datastoreMapping = embMmdMapping.getDatastoreMapping(j);
this.addDatastoreMapping(datastoreMapping);
if (this.mmd.isPrimaryKey()) {
// Overall embedded field should be part of PK, so make all datastore fields part of it
Column col = datastoreMapping.getColumn();
if (col != null) {
col.setPrimaryKey();
}
}
}
}
}
use of org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping in project datanucleus-rdbms by datanucleus.
the class PersistableMapping method prepareDatastoreMapping.
/**
* Method to prepare the PC mapping and add its associated datastore mappings.
* @param clr The ClassLoaderResolver
*/
protected void prepareDatastoreMapping(ClassLoaderResolver clr) {
if (roleForMember == FieldRole.ROLE_COLLECTION_ELEMENT) {
// TODO Handle creation of columns in join table for collection of PCs
} else if (roleForMember == FieldRole.ROLE_ARRAY_ELEMENT) {
// TODO Handle creation of columns in join table for array of PCs
} else if (roleForMember == FieldRole.ROLE_MAP_KEY) {
// TODO Handle creation of columns in join table for map of PCs as keys
} else if (roleForMember == FieldRole.ROLE_MAP_VALUE) {
// TODO Handle creation of columns in join table for map of PCs as values
} else {
// Either one end of a 1-1 relation, or the N end of a N-1
AbstractClassMetaData refCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(mmd.getType(), clr);
JavaTypeMapping referenceMapping = null;
if (refCmd == null) {
// User stupidity
throw new NucleusUserException("You have a field " + mmd.getFullFieldName() + " that has type " + mmd.getTypeName() + " but this type has no known metadata. Your mapping is incorrect");
}
if (refCmd.getInheritanceMetaData() != null && refCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
// 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) {
// TODO Only log this when it is really necessary. In some situations it is fine
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");
}
} else {
// TODO Throw an exception ?
return;
}
// TODO We need a mapping for each of the possible subclass tables
referenceMapping = storeMgr.getDatastoreClass(cmds[0].getFullClassName(), clr).getIdMapping();
} else if (refCmd.getInheritanceMetaData() != null && refCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
// Find the other side of the relation
DatastoreClass refTable = null;
if (refCmd instanceof ClassMetaData && !((ClassMetaData) refCmd).isAbstract()) {
refTable = storeMgr.getDatastoreClass(refCmd.getFullClassName(), clr);
} else {
Collection<String> refSubclasses = storeMgr.getSubClassesForClass(refCmd.getFullClassName(), true, clr);
if (refSubclasses != null && !refSubclasses.isEmpty()) {
// if only 1 subclass then use that
String refSubclassName = refSubclasses.iterator().next();
refTable = storeMgr.getDatastoreClass(refSubclassName, clr);
if (refSubclasses.size() > 1) {
NucleusLogger.DATASTORE_SCHEMA.info("Field " + mmd.getFullFieldName() + " is a 1-1/N-1 relation and the other side had multiple possible classes " + "to which to create a foreign-key. Using first possible (" + refSubclassName + ")");
}
}
}
if (refTable != null) {
referenceMapping = refTable.getIdMapping();
} else {
throw new NucleusUserException("Field " + mmd.getFullFieldName() + " represents either a 1-1 relation, " + "or a N-1 relation where the other end uses \"complete-table\" inheritance strategy and either no table was found, or multiple possible tables!");
}
} else {
// Default is to use the ID of the related object
// TODO Add option to use a natural-id in the other class. Find the mapping using the targetColumnName
referenceMapping = storeMgr.getDatastoreClass(mmd.getType().getName(), clr).getIdMapping();
}
// Generate a mapping from the columns of the referenced object to this mapping's ColumnMetaData
CorrespondentColumnsMapper correspondentColumnsMapping = new CorrespondentColumnsMapper(mmd, table, referenceMapping, true);
// Find any related field where this is part of a bidirectional relation
RelationType relationType = mmd.getRelationType(clr);
boolean createDatastoreMappings = true;
if (relationType == RelationType.MANY_TO_ONE_BI) {
AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
// TODO Cater for more than 1 related field
createDatastoreMappings = (relatedMmds[0].getJoinMetaData() == null);
} else if (// TODO If join table then don't need this
relationType == RelationType.ONE_TO_ONE_BI) {
// Put the FK at the end without "mapped-by"
createDatastoreMappings = (mmd.getMappedBy() == null);
}
if (mmd.getJoinMetaData() != null && (relationType == RelationType.MANY_TO_ONE_UNI || relationType == RelationType.ONE_TO_ONE_UNI || relationType == RelationType.ONE_TO_ONE_BI)) {
if (relationType == RelationType.ONE_TO_ONE_UNI || relationType == RelationType.ONE_TO_ONE_BI) {
throw new NucleusUserException("We do not currently support 1-1 relations via join table : " + mmd.getFullFieldName());
}
// create join table
storeMgr.newJoinTable(table, mmd, clr);
} else {
// Loop through the datastore fields in the referenced class and create a datastore field for each
for (int i = 0; i < referenceMapping.getNumberOfDatastoreMappings(); i++) {
DatastoreMapping refDatastoreMapping = referenceMapping.getDatastoreMapping(i);
JavaTypeMapping mapping = storeMgr.getMappingManager().getMapping(refDatastoreMapping.getJavaTypeMapping().getJavaType());
this.addJavaTypeMapping(mapping);
// Create physical datastore columns where we require a FK link to the related table.
if (createDatastoreMappings) {
// Find the Column MetaData that maps to the referenced datastore field
ColumnMetaData colmd = correspondentColumnsMapping.getColumnMetaDataByIdentifier(refDatastoreMapping.getColumn().getIdentifier());
if (colmd == null) {
throw new NucleusUserException(Localiser.msg("041038", refDatastoreMapping.getColumn().getIdentifier(), toString())).setFatal();
}
// Create a Datastore field to equate to the referenced classes datastore field
MappingManager mmgr = storeMgr.getMappingManager();
Column col = mmgr.createColumn(mmd, table, mapping, colmd, refDatastoreMapping.getColumn(), clr);
// Add its datastore mapping
DatastoreMapping datastoreMapping = mmgr.createDatastoreMapping(mapping, col, refDatastoreMapping.getJavaTypeMapping().getJavaTypeForDatastoreMapping(i));
this.addDatastoreMapping(datastoreMapping);
} else {
mapping.setReferenceMapping(referenceMapping);
}
}
}
}
}
Aggregations