Search in sources :

Example 1 with 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 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;
}
Also used : Column(org.datanucleus.store.rdbms.table.Column) DatastoreMapping(org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass)

Example 2 with 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;
}
Also used : DatastoreMapping(org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping) ValueGenerationStrategy(org.datanucleus.metadata.ValueGenerationStrategy) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData)

Example 3 with 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();
                }
            }
        }
    }
}
Also used : DatastoreMapping(org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping) Column(org.datanucleus.store.rdbms.table.Column) MappingManager(org.datanucleus.store.rdbms.mapping.MappingManager) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 4 with DatastoreMapping

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);
                }
            }
        }
    }
}
Also used : NucleusUserException(org.datanucleus.exceptions.NucleusUserException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) DatastoreMapping(org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping) Column(org.datanucleus.store.rdbms.table.Column) RelationType(org.datanucleus.metadata.RelationType) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) MappingManager(org.datanucleus.store.rdbms.mapping.MappingManager) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ClassMetaData(org.datanucleus.metadata.ClassMetaData) CorrespondentColumnsMapper(org.datanucleus.store.rdbms.mapping.CorrespondentColumnsMapper)

Aggregations

DatastoreMapping (org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping)4 Column (org.datanucleus.store.rdbms.table.Column)3 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)3 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)2 MappingManager (org.datanucleus.store.rdbms.mapping.MappingManager)2 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)1 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)1 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)1 ClassMetaData (org.datanucleus.metadata.ClassMetaData)1 RelationType (org.datanucleus.metadata.RelationType)1 ValueGenerationStrategy (org.datanucleus.metadata.ValueGenerationStrategy)1 CorrespondentColumnsMapper (org.datanucleus.store.rdbms.mapping.CorrespondentColumnsMapper)1