Search in sources :

Example 86 with ObjectProvider

use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.

the class PersistentClassROF method getObject.

/**
 * Method to convert the current ResultSet row into a persistable Object.
 * @return The persistable object.
 */
public T getObject() {
    // Find the class of the returned object in this row of the ResultSet
    String className = null;
    boolean requiresInheritanceCheck = true;
    StatementMappingIndex discrimMapIdx = resultMapping.getMappingForMemberPosition(SurrogateColumnType.DISCRIMINATOR.getFieldNumber());
    if (discrimMapIdx != null) {
        // Discriminator mapping registered so use that
        try {
            String discrimValue = rs.getString(discrimMapIdx.getColumnPositions()[0]);
            if (discrimValue == null) {
                // Discriminator has no value so return null object
                NucleusLogger.DATASTORE_RETRIEVE.debug("Value of discriminator is null so assuming object is null");
                return null;
            }
            JavaTypeMapping discrimMapping = discrimMapIdx.getMapping();
            DiscriminatorMetaData dismd = (discrimMapping != null ? discrimMapping.getTable().getDiscriminatorMetaData() : null);
            className = ec.getMetaDataManager().getClassNameFromDiscriminatorValue(discrimValue, dismd);
            requiresInheritanceCheck = false;
        } catch (SQLException sqle) {
            NucleusLogger.DATASTORE_RETRIEVE.debug("Exception obtaining value of discriminator : " + sqle.getMessage());
        }
    } else if (resultMapping.getNucleusTypeColumnName() != null) {
        // Extract the object type using the NucleusType column (if available)
        try {
            className = rs.getString(resultMapping.getNucleusTypeColumnName());
            if (className == null) {
                // Discriminator has no value so return null object
                NucleusLogger.DATASTORE_RETRIEVE.debug("Value of determiner column is null so assuming object is null");
                return null;
            }
            className = className.trim();
            requiresInheritanceCheck = false;
        } catch (SQLException sqle) {
        // NucleusType column not found so ignore
        }
    }
    ClassLoaderResolver clr = ec.getClassLoaderResolver();
    Class pcClassForObject = persistentClass;
    if (className != null) {
        Class cls = (Class) resolvedClasses.get(className);
        if (cls != null) {
            pcClassForObject = cls;
        } else {
            if (persistentClass.getName().equals(className)) {
                pcClassForObject = persistentClass;
            } else {
                pcClassForObject = clr.classForName(className, persistentClass.getClassLoader());
            }
            resolvedClasses.put(className, pcClassForObject);
        }
    }
    if (requiresInheritanceCheck) {
        // Check if no instantiable subclasses
        String[] subclasses = ec.getMetaDataManager().getSubclassesForClass(pcClassForObject.getName(), false);
        if (subclasses == null || subclasses.length == 0) {
            requiresInheritanceCheck = false;
        }
    }
    String warnMsg = null;
    if (Modifier.isAbstract(pcClassForObject.getModifiers())) {
        // Persistent class is abstract so we can't create instances of that type!
        // This can happen if the user is using subclass-table and hasn't provided a discriminator in
        // the table. Try going out one level and find a (single) concrete subclass
        // TODO make this more robust and go out further
        String[] subclasses = ec.getMetaDataManager().getSubclassesForClass(pcClassForObject.getName(), false);
        if (subclasses != null) {
            Class concreteSubclass = null;
            int numConcreteSubclasses = 0;
            for (int i = 0; i < subclasses.length; i++) {
                Class subcls = clr.classForName(subclasses[i]);
                if (!Modifier.isAbstract(subcls.getModifiers())) {
                    numConcreteSubclasses++;
                    concreteSubclass = subcls;
                }
            }
            if (numConcreteSubclasses == 1) {
                // Only one possible subclass, so use that
                NucleusLogger.DATASTORE_RETRIEVE.warn(Localiser.msg("052300", pcClassForObject.getName(), concreteSubclass.getName()));
                pcClassForObject = concreteSubclass;
            } else if (numConcreteSubclasses == 0) {
                throw new NucleusUserException(Localiser.msg("052301", pcClassForObject.getName()));
            } else {
                // More than 1 possible so notify the user. Really should return the abstract
                warnMsg = "Found type=" + pcClassForObject + " but abstract and more than 1 concrete subclass (" + StringUtils.objectArrayToString(subclasses) + "). Really you need a discriminator to help identifying the type. Choosing " + concreteSubclass;
                pcClassForObject = concreteSubclass;
                requiresInheritanceCheck = true;
            }
        }
    }
    // Find the statement mappings and field numbers to use for the result class
    // Caters for persistent-interfaces and the result class being an implementation
    AbstractClassMetaData cmd = ec.getMetaDataManager().getMetaDataForClass(pcClassForObject, clr);
    if (cmd == null) {
        // TODO Improve this and check PK cols
        return null;
    }
    int[] fieldNumbers = resultMapping.getMemberNumbers();
    // TODO We need this on the first object only to generate the ResultSetGetter; can we optimise this?
    StatementClassMapping mappingDefinition;
    int[] mappedFieldNumbers;
    if (rootCmd instanceof InterfaceMetaData) {
        // Persistent-interface : create new mapping definition for a result type of the implementation
        mappingDefinition = new StatementClassMapping();
        mappingDefinition.setNucleusTypeColumnName(resultMapping.getNucleusTypeColumnName());
        mappedFieldNumbers = new int[fieldNumbers.length];
        for (int i = 0; i < fieldNumbers.length; i++) {
            AbstractMemberMetaData mmd = rootCmd.getMetaDataForManagedMemberAtAbsolutePosition(fieldNumbers[i]);
            mappedFieldNumbers[i] = cmd.getAbsolutePositionOfMember(mmd.getName());
            mappingDefinition.addMappingForMember(mappedFieldNumbers[i], resultMapping.getMappingForMemberPosition(fieldNumbers[i]));
        }
    } else {
        // Persistent class
        mappingDefinition = resultMapping;
        mappedFieldNumbers = fieldNumbers;
    }
    if (resultSetGetter == null) {
        // Use this result mapping definition for our ResultSetGetter
        this.resultSetGetter = new ResultSetGetter(ec, rs, mappingDefinition, rootCmd);
    }
    // Extract any surrogate version
    VersionMetaData vermd = cmd.getVersionMetaDataForClass();
    Object surrogateVersion = null;
    StatementMappingIndex versionMapping = null;
    if (vermd != null) {
        if (vermd.getFieldName() == null) {
            versionMapping = resultMapping.getMappingForMemberPosition(SurrogateColumnType.VERSION.getFieldNumber());
        } else {
            AbstractMemberMetaData vermmd = cmd.getMetaDataForMember(vermd.getFieldName());
            versionMapping = resultMapping.getMappingForMemberPosition(vermmd.getAbsoluteFieldNumber());
        }
    }
    if (versionMapping != null) {
        // Surrogate version column returned by query
        JavaTypeMapping mapping = versionMapping.getMapping();
        surrogateVersion = mapping.getObject(ec, rs, versionMapping.getColumnPositions());
    }
    // Extract the object from the ResultSet
    T obj = null;
    boolean needToSetVersion = false;
    if (persistentClass.isInterface() && !cmd.isImplementationOfPersistentDefinition()) {
        // Querying by interface, and not a generated implementation so use the metadata for the interface
        cmd = ec.getMetaDataManager().getMetaDataForInterface(persistentClass, clr);
        if (cmd == null) {
            // Fallback to the value we had
            cmd = ec.getMetaDataManager().getMetaDataForClass(pcClassForObject, clr);
        }
    }
    if (cmd.getIdentityType() == IdentityType.APPLICATION) {
        // Check if the PK field(s) are all null (implies null object, when using OUTER JOIN)
        int[] pkNumbers = cmd.getPKMemberPositions();
        boolean nullObject = true;
        for (int i = 0; i < pkNumbers.length; i++) {
            StatementMappingIndex pkIdx = mappingDefinition.getMappingForMemberPosition(pkNumbers[i]);
            if (pkIdx == null) {
                throw new NucleusException("You have just executed an SQL statement yet the information " + "for the primary key column(s) is not available! Please generate a testcase and report this issue");
            }
            int[] colPositions = pkIdx.getColumnPositions();
            for (int j = 0; j < colPositions.length; j++) {
                try {
                    Object pkObj = rs.getObject(colPositions[j]);
                    if (pkObj != null) {
                        nullObject = false;
                        break;
                    }
                } catch (SQLException sqle) {
                    NucleusLogger.DATASTORE_RETRIEVE.warn("Exception thrown while retrieving results ", sqle);
                }
                if (!nullObject) {
                    break;
                }
            }
        }
        if (!nullObject) {
            // Retrieve the object with this application-identity
            if (warnMsg != null) {
                NucleusLogger.DATASTORE_RETRIEVE.warn(warnMsg);
            }
            Object id = IdentityUtils.getApplicationIdentityForResultSetRow(ec, cmd, pcClassForObject, requiresInheritanceCheck, resultSetGetter);
            String idClassName = IdentityUtils.getTargetClassNameForIdentity(id);
            if (idClassName != null) {
                // "identity" defines the class name
                pcClassForObject = clr.classForName(idClassName);
            }
            obj = findObjectWithIdAndLoadFields(id, mappedFieldNumbers, pcClassForObject, cmd, surrogateVersion);
        }
    } else if (cmd.getIdentityType() == IdentityType.DATASTORE) {
        // Generate the "id" for this object (of type pcClassForObject), and find the object for that
        StatementMappingIndex datastoreIdMapping = resultMapping.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
        JavaTypeMapping mapping = datastoreIdMapping.getMapping();
        Object id = mapping.getObject(ec, rs, datastoreIdMapping.getColumnPositions());
        if (id != null) {
            String idClassName = IdentityUtils.getTargetClassNameForIdentity(id);
            if (!pcClassForObject.getName().equals(idClassName)) {
                // Get a DatastoreId for the right inheritance level
                id = ec.getNucleusContext().getIdentityManager().getDatastoreId(pcClassForObject.getName(), IdentityUtils.getTargetKeyForDatastoreIdentity(id));
            }
            if (warnMsg != null) {
                NucleusLogger.DATASTORE_RETRIEVE.warn(warnMsg);
            }
            if (mappedFieldNumbers == null) {
                obj = (T) ec.findObject(id, false, requiresInheritanceCheck, null);
                needToSetVersion = true;
            } else {
                obj = findObjectWithIdAndLoadFields(id, mappedFieldNumbers, requiresInheritanceCheck ? null : pcClassForObject, cmd, surrogateVersion);
            }
        }
    } else if (cmd.getIdentityType() == IdentityType.NONDURABLE) {
        String classNameForId = className;
        if (className == null) {
            // No discriminator info from the query, so just fallback to default type
            classNameForId = cmd.getFullClassName();
        }
        Object id = ec.newObjectId(classNameForId, null);
        if (mappedFieldNumbers == null) {
            obj = (T) ec.findObject(id, false, requiresInheritanceCheck, null);
            needToSetVersion = true;
        } else {
            obj = findObjectWithIdAndLoadFields(id, fieldNumbers, pcClassForObject, cmd, surrogateVersion);
        }
    }
    if (obj != null && needToSetVersion) {
        // Set the version of the object where possible
        if (surrogateVersion != null) {
            ObjectProvider objOP = ec.findObjectProvider(obj);
            objOP.setVersion(surrogateVersion);
        } else {
            if (vermd != null && vermd.getFieldName() != null) {
                // Version stored in a normal field
                int versionFieldNumber = rootCmd.getMetaDataForMember(vermd.getFieldName()).getAbsoluteFieldNumber();
                if (resultMapping.getMappingForMemberPosition(versionFieldNumber) != null) {
                    ObjectProvider objOP = ec.findObjectProvider(obj);
                    Object verFieldValue = objOP.provideField(versionFieldNumber);
                    if (verFieldValue != null) {
                        objOP.setVersion(verFieldValue);
                    }
                }
            }
        }
    }
    return obj;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLException(java.sql.SQLException) VersionMetaData(org.datanucleus.metadata.VersionMetaData) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ResultSetGetter(org.datanucleus.store.rdbms.fieldmanager.ResultSetGetter) DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) InterfaceMetaData(org.datanucleus.metadata.InterfaceMetaData) ObjectProvider(org.datanucleus.state.ObjectProvider) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 87 with ObjectProvider

use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.

the class QueryToSQLMapper method getValueForObjectField.

/**
 * Convenience method to return the value of a field of the supplied object.
 * If the object is null then returns null for the field.
 * @param obj The object
 * @param fieldName The field name
 * @return The field value
 */
protected Object getValueForObjectField(Object obj, String fieldName) {
    if (obj != null) {
        Object paramFieldValue = null;
        if (ec.getApiAdapter().isPersistable(obj)) {
            ObjectProvider paramOP = ec.findObjectProvider(obj);
            AbstractClassMetaData paramCmd = ec.getMetaDataManager().getMetaDataForClass(obj.getClass(), clr);
            AbstractMemberMetaData paramFieldMmd = paramCmd.getMetaDataForMember(fieldName);
            if (paramOP != null) {
                paramOP.isLoaded(paramFieldMmd.getAbsoluteFieldNumber());
                paramFieldValue = paramOP.provideField(paramFieldMmd.getAbsoluteFieldNumber());
            } else {
                paramFieldValue = ClassUtils.getValueOfFieldByReflection(obj, fieldName);
            }
        } else {
            paramFieldValue = ClassUtils.getValueOfFieldByReflection(obj, fieldName);
        }
        return paramFieldValue;
    }
    return null;
}
Also used : ObjectProvider(org.datanucleus.state.ObjectProvider) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData)

Example 88 with ObjectProvider

use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.

the class OracleSerialisedPCMapping method insertPostProcessing.

/**
 * Retrieve the empty BLOB created by the insert statement and write out the
 * current BLOB field value to the Oracle BLOB object
 * @param op the current ObjectProvider
 */
public void insertPostProcessing(ObjectProvider op) {
    Object value = op.provideField(mmd.getAbsoluteFieldNumber());
    ObjectProvider sm = null;
    if (value != null) {
        ExecutionContext ec = op.getExecutionContext();
        sm = ec.findObjectProvider(value);
        if (sm == null || sm.getExecutionContext().getApiAdapter().getExecutionContext(value) == null) {
            // Assign a ObjectProvider to the serialised object since none present
            sm = ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, value, false, op, mmd.getAbsoluteFieldNumber());
        }
    }
    if (sm != null) {
        sm.setStoringPC();
    }
    // Generate the contents for the BLOB
    byte[] bytes = new byte[0];
    if (value != null) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(value);
            bytes = baos.toByteArray();
        } catch (IOException e1) {
        // Do Nothing
        }
    }
    // Update the BLOB
    OracleBlobRDBMSMapping.updateBlobColumn(op, getTable(), getDatastoreMapping(0), bytes);
    if (sm != null) {
        sm.unsetStoringPC();
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) ObjectProvider(org.datanucleus.state.ObjectProvider) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) ObjectOutputStream(java.io.ObjectOutputStream)

Example 89 with ObjectProvider

use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.

the class PersistableMapping method preDelete.

/**
 * Method executed just before the owning object is deleted, allowing tidying up of any relation information.
 * @param op ObjectProvider for the owner
 */
public void preDelete(ObjectProvider op) {
    int fieldNumber = mmd.getAbsoluteFieldNumber();
    if (!op.isFieldLoaded(fieldNumber)) {
        // makes sure field is loaded
        try {
            op.loadField(fieldNumber);
        } catch (NucleusObjectNotFoundException onfe) {
            // Already deleted so just return
            return;
        }
    }
    Object pc = op.provideField(fieldNumber);
    pc = mmd.isSingleCollection() ? SCOUtils.singleCollectionValue(getStoreManager().getNucleusContext().getTypeManager(), pc) : pc;
    if (pc == null) {
        // Null value so nothing to do
        return;
    }
    ExecutionContext ec = op.getExecutionContext();
    ClassLoaderResolver clr = ec.getClassLoaderResolver();
    // N-1 Uni, so delete join table entry
    RelationType relationType = mmd.getRelationType(clr);
    if (relationType == RelationType.MANY_TO_ONE_UNI) {
        // Update join table entry
        PersistableRelationStore store = (PersistableRelationStore) storeMgr.getBackingStoreForField(clr, mmd, mmd.getType());
        store.remove(op);
    }
    // Check if we should delete the related object when this object is deleted
    boolean dependent = mmd.isDependent();
    if (mmd.isCascadeRemoveOrphans()) {
        // JPA allows "orphan removal" to define deletion of the other side
        dependent = true;
    }
    // Check if the field has a FK defined
    AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
    // TODO Cater for more than 1 related field
    boolean hasFK = false;
    if (!dependent) {
        // Not dependent, so check if the datastore has a FK and will take care of it for us
        if (mmd.getForeignKeyMetaData() != null) {
            hasFK = true;
        }
        if (RelationType.isBidirectional(relationType) && relatedMmds[0].getForeignKeyMetaData() != null) {
            hasFK = true;
        }
        if (ec.getStringProperty(PropertyNames.PROPERTY_DELETION_POLICY).equals("JDO2")) {
            // JDO doesn't currently take note of foreign-key
            hasFK = false;
        }
    }
    // There may be some corner cases that this code doesn't yet cater for
    if (relationType == RelationType.ONE_TO_ONE_UNI || (relationType == RelationType.ONE_TO_ONE_BI && mmd.getMappedBy() == null)) {
        // 1-1 with FK at this side (owner of the relation)
        if (dependent) {
            boolean relatedObjectDeleted = ec.getApiAdapter().isDeleted(pc);
            if (isNullable() && !relatedObjectDeleted) {
                // Other object not yet deleted, but the field is nullable so just null out the FK
                // TODO Not doing this would cause errors in 1-1 uni relations (e.g AttachDetachTest)
                // TODO Log this since it affects the resultant objects
                op.replaceFieldMakeDirty(fieldNumber, null);
                storeMgr.getPersistenceHandler().updateObject(op, new int[] { fieldNumber });
                if (!relatedObjectDeleted) {
                    // Mark the other object for deletion since not yet tagged
                    ec.deleteObjectInternal(pc);
                }
            } else {
                // Can't just delete the other object since that would cause a FK constraint violation. Do nothing - handled by DeleteRequest on other object
                if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                    NucleusLogger.DATASTORE_PERSIST.debug(Localiser.msg("041017", StringUtils.toJVMIDString(op.getObject()), mmd.getFullFieldName()));
                }
            }
        } else {
            // We're deleting the FK at this side so shouldn't be an issue
            AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaDataForObject(clr, op.getObject(), pc);
            if (relatedMmd != null) {
                ObjectProvider otherOP = ec.findObjectProvider(pc);
                if (otherOP != null) {
                    // Managed Relations : 1-1 bidir, so null out the object at the other
                    Object currentValue = otherOP.provideField(relatedMmd.getAbsoluteFieldNumber());
                    if (currentValue != null) {
                        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                            NucleusLogger.PERSISTENCE.debug(Localiser.msg("041019", StringUtils.toJVMIDString(pc), relatedMmd.getFullFieldName(), op.getObjectAsPrintable()));
                        }
                        otherOP.replaceFieldMakeDirty(relatedMmd.getAbsoluteFieldNumber(), null);
                        if (ec.getManageRelations()) {
                            otherOP.getExecutionContext().getRelationshipManager(otherOP).relationChange(relatedMmd.getAbsoluteFieldNumber(), op.getObject(), null);
                        }
                    }
                }
            }
        }
    } else if (relationType == RelationType.ONE_TO_ONE_BI && mmd.getMappedBy() != null) {
        // 1-1 with FK at other side
        DatastoreClass relatedTable = storeMgr.getDatastoreClass(relatedMmds[0].getClassName(), clr);
        JavaTypeMapping relatedMapping = relatedTable.getMemberMapping(relatedMmds[0]);
        boolean isNullable = relatedMapping.isNullable();
        ObjectProvider otherOP = ec.findObjectProvider(pc);
        if (dependent) {
            if (isNullable) {
                // Null out the FK in the datastore using a direct update (since we are deleting)
                otherOP.replaceFieldMakeDirty(relatedMmds[0].getAbsoluteFieldNumber(), null);
                storeMgr.getPersistenceHandler().updateObject(otherOP, new int[] { relatedMmds[0].getAbsoluteFieldNumber() });
            }
            // Mark the other object for deletion
            ec.deleteObjectInternal(pc);
        } else if (!hasFK) {
            if (isNullable()) {
                Object currentRelatedValue = otherOP.provideField(relatedMmds[0].getAbsoluteFieldNumber());
                if (currentRelatedValue != null) {
                    // Null out the FK in the datastore using a direct update (since we are deleting)
                    otherOP.replaceFieldMakeDirty(relatedMmds[0].getAbsoluteFieldNumber(), null);
                    storeMgr.getPersistenceHandler().updateObject(otherOP, new int[] { relatedMmds[0].getAbsoluteFieldNumber() });
                    // Managed Relations : 1-1 bidir, so null out the object at the other
                    if (ec.getManageRelations()) {
                        otherOP.getExecutionContext().getRelationshipManager(otherOP).relationChange(relatedMmds[0].getAbsoluteFieldNumber(), op.getObject(), null);
                    }
                }
            } else {
            // TODO Remove it
            }
        } else {
        // User has a FK defined (in MetaData) so let the datastore take care of it
        }
    } else if (relationType == RelationType.MANY_TO_ONE_BI) {
        ObjectProvider otherOP = ec.findObjectProvider(pc);
        if (relatedMmds[0].getJoinMetaData() == null) {
            // N-1 with FK at this side
            if (otherOP.isDeleting()) {
            // Other object is being deleted too but this side has the FK so just delete this object
            } else {
                // Other object is not being deleted so delete it if necessary
                if (dependent) {
                    if (isNullable()) {
                        // TODO Datastore nullability info can be unreliable so try to avoid this call
                        // Null out the FK in the datastore using a direct update (since we are deleting)
                        op.replaceFieldMakeDirty(fieldNumber, null);
                        storeMgr.getPersistenceHandler().updateObject(op, new int[] { fieldNumber });
                    }
                    if (ec.getApiAdapter().isDeleted(pc)) {
                    // Object is already tagged for deletion but we're deleting the FK so leave til flush()
                    } else {
                        // Mark the other object for deletion
                        ec.deleteObjectInternal(pc);
                    }
                } else {
                    // Managed Relations : remove element from collection/map
                    if (relatedMmds[0].hasCollection()) {
                        // Only update the other side if not already being deleted
                        if (!ec.getApiAdapter().isDeleted(otherOP.getObject()) && !otherOP.isDeleting()) {
                            // Make sure the other object is updated in any caches
                            ec.markDirty(otherOP, false);
                            // Make sure collection field is loaded
                            otherOP.isLoaded(relatedMmds[0].getAbsoluteFieldNumber());
                            Collection otherColl = (Collection) otherOP.provideField(relatedMmds[0].getAbsoluteFieldNumber());
                            if (otherColl != null) {
                                if (ec.getManageRelations()) {
                                    otherOP.getExecutionContext().getRelationshipManager(otherOP).relationRemove(relatedMmds[0].getAbsoluteFieldNumber(), op.getObject());
                                }
                                // TODO Localise this message
                                NucleusLogger.PERSISTENCE.debug("ManagedRelationships : delete of object causes removal from collection at " + relatedMmds[0].getFullFieldName());
                                otherColl.remove(op.getObject());
                            }
                        }
                    } else if (relatedMmds[0].hasMap()) {
                    // TODO Cater for maps, but what is the key/value pair ?
                    }
                }
            }
        } else {
            // N-1 with join table so no FK here so need to remove from Collection/Map first? (managed relations)
            if (dependent) {
                // Mark the other object for deletion
                ec.deleteObjectInternal(pc);
            } else {
                // Managed Relations : remove element from collection/map
                if (relatedMmds[0].hasCollection()) {
                    // Only update the other side if not already being deleted
                    if (!ec.getApiAdapter().isDeleted(otherOP.getObject()) && !otherOP.isDeleting()) {
                        // Make sure the other object is updated in any caches
                        ec.markDirty(otherOP, false);
                        // Make sure the other object has the collection loaded so does this change
                        otherOP.isLoaded(relatedMmds[0].getAbsoluteFieldNumber());
                        Collection otherColl = (Collection) otherOP.provideField(relatedMmds[0].getAbsoluteFieldNumber());
                        if (otherColl != null) {
                            // TODO Localise this
                            NucleusLogger.PERSISTENCE.debug("ManagedRelationships : delete of object causes removal from collection at " + relatedMmds[0].getFullFieldName());
                            otherColl.remove(op.getObject());
                        }
                    }
                } else if (relatedMmds[0].hasMap()) {
                // TODO Cater for maps, but what is the key/value pair ?
                }
            }
        }
    } else if (relationType == RelationType.MANY_TO_ONE_UNI) {
        // N-1 uni with join table
        if (dependent) {
            // Mark the other object for deletion
            ec.deleteObjectInternal(pc);
        }
    } else {
    // No relation so what is this field ?
    }
}
Also used : ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) ExecutionContext(org.datanucleus.ExecutionContext) RelationType(org.datanucleus.metadata.RelationType) Collection(java.util.Collection) SCOCollection(org.datanucleus.store.types.SCOCollection) ObjectProvider(org.datanucleus.state.ObjectProvider) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) PersistableRelationStore(org.datanucleus.store.types.scostore.PersistableRelationStore)

Example 90 with ObjectProvider

use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.

the class PersistableMapping method getValueForDatastoreMapping.

/**
 * Method to return the value to be stored in the specified datastore index given the overall value for this java type.
 * @param nucleusCtx Context
 * @param index The datastore index
 * @param value The overall value for this java type
 * @return The value for this datastore index
 */
public Object getValueForDatastoreMapping(NucleusContext nucleusCtx, int index, Object value) {
    ExecutionContext ec = nucleusCtx.getApiAdapter().getExecutionContext(value);
    if (cmd == null) {
        cmd = nucleusCtx.getMetaDataManager().getMetaDataForClass(getType(), ec != null ? ec.getClassLoaderResolver() : nucleusCtx.getClassLoaderResolver(null));
    }
    if (cmd.getIdentityType() == IdentityType.APPLICATION) {
        AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(cmd.getPKMemberPositions()[index]);
        ObjectProvider op = null;
        if (ec != null) {
            op = ec.findObjectProvider(value);
        }
        if (op == null) {
            // Transient or detached maybe, so use reflection to get PK field values
            if (mmd instanceof FieldMetaData) {
                return ClassUtils.getValueOfFieldByReflection(value, mmd.getName());
            }
            return ClassUtils.getValueOfMethodByReflection(value, ClassUtils.getJavaBeanGetterName(mmd.getName(), false));
        }
        if (!mmd.isPrimaryKey()) {
            // Make sure the field is loaded
            op.isLoaded(mmd.getAbsoluteFieldNumber());
        }
        FieldManager fm = new SingleValueFieldManager();
        op.provideFields(new int[] { mmd.getAbsoluteFieldNumber() }, fm);
        return fm.fetchObjectField(mmd.getAbsoluteFieldNumber());
    } else if (cmd.getIdentityType() == IdentityType.DATASTORE) {
        Object id = nucleusCtx.getApiAdapter().getIdForObject(value);
        return id != null ? IdentityUtils.getTargetKeyForDatastoreIdentity(id) : null;
    }
    return null;
}
Also used : FieldMetaData(org.datanucleus.metadata.FieldMetaData) ExecutionContext(org.datanucleus.ExecutionContext) AppIDObjectIdFieldManager(org.datanucleus.store.rdbms.mapping.AppIDObjectIdFieldManager) SingleValueFieldManager(org.datanucleus.store.fieldmanager.SingleValueFieldManager) FieldManager(org.datanucleus.store.fieldmanager.FieldManager) SingleValueFieldManager(org.datanucleus.store.fieldmanager.SingleValueFieldManager) ObjectProvider(org.datanucleus.state.ObjectProvider) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

ObjectProvider (org.datanucleus.state.ObjectProvider)160 ExecutionContext (org.datanucleus.ExecutionContext)85 Iterator (java.util.Iterator)43 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)34 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)25 Map (java.util.Map)22 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)22 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)21 SQLException (java.sql.SQLException)17 Collection (java.util.Collection)16 ApiAdapter (org.datanucleus.api.ApiAdapter)16 NucleusObjectNotFoundException (org.datanucleus.exceptions.NucleusObjectNotFoundException)16 SCOCollectionIterator (org.datanucleus.store.types.SCOCollectionIterator)16 ArrayList (java.util.ArrayList)14 HashSet (java.util.HashSet)14 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)14 NucleusException (org.datanucleus.exceptions.NucleusException)13 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)13 ListIterator (java.util.ListIterator)12 SQLController (org.datanucleus.store.rdbms.SQLController)12