Search in sources :

Example 1 with FieldManager

use of org.datanucleus.store.fieldmanager.FieldManager in project datanucleus-rdbms by datanucleus.

the class LocateBulkRequest method processResults.

private ObjectProvider[] processResults(ResultSet rs, ObjectProvider[] ops) throws SQLException {
    List<ObjectProvider> missingOps = new ArrayList<>();
    for (int i = 0; i < ops.length; i++) {
        missingOps.add(ops[i]);
    }
    ExecutionContext ec = ops[0].getExecutionContext();
    while (rs.next()) {
        FieldManager resultFM = new ResultSetGetter(ec, rs, resultMapping, cmd);
        Object id = null;
        Object key = null;
        if (cmd.getIdentityType() == IdentityType.DATASTORE) {
            StatementMappingIndex idx = resultMapping.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
            JavaTypeMapping idMapping = idx.getMapping();
            key = idMapping.getObject(ec, rs, idx.getColumnPositions());
            if (IdentityUtils.isDatastoreIdentity(key)) {
                // If mapping is OIDMapping then returns an OID rather than the column value
                key = IdentityUtils.getTargetKeyForDatastoreIdentity(key);
            }
        } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
            if (cmd.usesSingleFieldIdentityClass()) {
                int[] pkFieldNums = cmd.getPKMemberPositions();
                AbstractMemberMetaData pkMmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkFieldNums[0]);
                if (pkMmd.getType() == int.class) {
                    key = resultFM.fetchIntField(pkFieldNums[0]);
                } else if (pkMmd.getType() == short.class) {
                    key = resultFM.fetchShortField(pkFieldNums[0]);
                } else if (pkMmd.getType() == long.class) {
                    key = resultFM.fetchLongField(pkFieldNums[0]);
                } else if (pkMmd.getType() == char.class) {
                    key = resultFM.fetchCharField(pkFieldNums[0]);
                } else if (pkMmd.getType() == boolean.class) {
                    key = resultFM.fetchBooleanField(pkFieldNums[0]);
                } else if (pkMmd.getType() == byte.class) {
                    key = resultFM.fetchByteField(pkFieldNums[0]);
                } else if (pkMmd.getType() == double.class) {
                    key = resultFM.fetchDoubleField(pkFieldNums[0]);
                } else if (pkMmd.getType() == float.class) {
                    key = resultFM.fetchFloatField(pkFieldNums[0]);
                } else if (pkMmd.getType() == String.class) {
                    key = resultFM.fetchStringField(pkFieldNums[0]);
                } else {
                    key = resultFM.fetchObjectField(pkFieldNums[0]);
                }
            } else {
                id = IdentityUtils.getApplicationIdentityForResultSetRow(ec, cmd, null, true, resultFM);
            }
        }
        // Find which ObjectProvider this row is for
        ObjectProvider op = null;
        for (ObjectProvider missingOp : missingOps) {
            Object opId = missingOp.getInternalObjectId();
            if (cmd.getIdentityType() == IdentityType.DATASTORE) {
                Object opKey = IdentityUtils.getTargetKeyForDatastoreIdentity(opId);
                if (key != null && opKey.getClass() != key.getClass()) {
                    opKey = TypeConversionHelper.convertTo(opKey, key.getClass());
                }
                if (opKey.equals(key)) {
                    op = missingOp;
                    break;
                }
            } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
                if (cmd.usesSingleFieldIdentityClass()) {
                    Object opKey = IdentityUtils.getTargetKeyForSingleFieldIdentity(opId);
                    if (opKey.equals(key)) {
                        op = missingOp;
                        break;
                    }
                } else {
                    if (opId.equals(id)) {
                        op = missingOp;
                        break;
                    }
                }
            }
        }
        if (op != null) {
            // Mark ObjectProvider as processed
            missingOps.remove(op);
            // Load up any unloaded fields that we have selected
            int[] selectedMemberNums = resultMapping.getMemberNumbers();
            int[] unloadedMemberNums = ClassUtils.getFlagsSetTo(op.getLoadedFields(), selectedMemberNums, false);
            if (unloadedMemberNums != null && unloadedMemberNums.length > 0) {
                op.replaceFields(unloadedMemberNums, resultFM);
            }
            // Load version if present and not yet set
            JavaTypeMapping versionMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, false);
            if (op.getTransactionalVersion() == null && versionMapping != null) {
                VersionMetaData currentVermd = table.getVersionMetaData();
                Object datastoreVersion = null;
                if (currentVermd != null) {
                    if (currentVermd.getFieldName() == null) {
                        // Surrogate version
                        // Why use true now?
                        versionMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, true);
                        StatementMappingIndex verIdx = resultMapping.getMappingForMemberPosition(SurrogateColumnType.VERSION.getFieldNumber());
                        datastoreVersion = versionMapping.getObject(ec, rs, verIdx.getColumnPositions());
                    } else {
                        datastoreVersion = op.provideField(cmd.getAbsolutePositionOfMember(currentVermd.getFieldName()));
                    }
                    op.setVersion(datastoreVersion);
                }
            }
        }
    }
    if (!missingOps.isEmpty()) {
        return missingOps.toArray(new ObjectProvider[missingOps.size()]);
    }
    return null;
}
Also used : FieldManager(org.datanucleus.store.fieldmanager.FieldManager) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) VersionMetaData(org.datanucleus.metadata.VersionMetaData) ArrayList(java.util.ArrayList) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) ResultSetGetter(org.datanucleus.store.rdbms.fieldmanager.ResultSetGetter) ExecutionContext(org.datanucleus.ExecutionContext) ObjectProvider(org.datanucleus.state.ObjectProvider) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 2 with FieldManager

use of org.datanucleus.store.fieldmanager.FieldManager in project datanucleus-rdbms by datanucleus.

the class PersistableMapping method setObjectAsValue.

/**
 * Method to set an object reference (FK) in the datastore.
 * @param ec The ExecutionContext
 * @param ps The Prepared Statement
 * @param param The parameter ids in the statement
 * @param value The value to put in the statement at these ids
 * @param ownerOP ObjectProvider for the owner object
 * @param ownerFieldNumber Field number of this PC object in the owner
 * @throws NotYetFlushedException Just put "null" in and throw "NotYetFlushedException", to be caught by ParameterSetter and will signal to the
 *     PC object being inserted that it needs to inform this object when it is inserted.
 */
private void setObjectAsValue(ExecutionContext ec, PreparedStatement ps, int[] param, Object value, ObjectProvider ownerOP, int ownerFieldNumber) {
    Object id;
    ApiAdapter api = ec.getApiAdapter();
    if (!api.isPersistable(value)) {
        throw new NucleusException(Localiser.msg("041016", value.getClass(), value)).setFatal();
    }
    ObjectProvider valueOP = ec.findObjectProvider(value);
    try {
        ClassLoaderResolver clr = ec.getClassLoaderResolver();
        // Check if the field is attributed in the datastore
        boolean hasDatastoreAttributedPrimaryKeyValues = hasDatastoreAttributedPrimaryKeyValues(ec.getMetaDataManager(), storeMgr, clr);
        boolean inserted = false;
        if (ownerFieldNumber >= 0) {
            // Field mapping : is this field of the related object present in the datastore?
            inserted = storeMgr.isObjectInserted(valueOP, ownerFieldNumber);
        } else if (mmd == null) {
            // Identity mapping : is the object inserted far enough to be considered of this mapping type?
            inserted = storeMgr.isObjectInserted(valueOP, type);
        }
        if (valueOP != null) {
            if (ec.getApiAdapter().isDetached(value) && valueOP.getReferencedPC() != null && ownerOP != null && mmd != null) {
                // Still detached but started attaching so replace the field with what will be the attached
                // Note that we have "fmd != null" here hence omitting any M-N relations where this is a join table
                // mapping
                ownerOP.replaceFieldMakeDirty(ownerFieldNumber, valueOP.getReferencedPC());
            }
            if (valueOP.isWaitingToBeFlushedToDatastore()) {
                try {
                    // Related object is not yet flushed to the datastore so flush it so we can set the FK
                    valueOP.flush();
                } catch (NotYetFlushedException nfe) {
                    // Could not flush it, maybe it has a relation to this object! so set as null TODO check nullability
                    if (ownerOP != null) {
                        ownerOP.updateFieldAfterInsert(value, ownerFieldNumber);
                    }
                    setObjectAsNull(ec, ps, param);
                    return;
                }
            }
        } else {
            if (ec.getApiAdapter().isDetached(value)) {
                // Field value is detached and not yet started attaching, so attach
                Object attachedValue = ec.persistObjectInternal(value, null, -1, ObjectProvider.PC);
                if (attachedValue != value && ownerOP != null) {
                    // Replace the field value if using copy-on-attach
                    ownerOP.replaceFieldMakeDirty(ownerFieldNumber, attachedValue);
                    // Work from attached value now that it is attached
                    value = attachedValue;
                }
                valueOP = ec.findObjectProvider(value);
            }
        }
        // 5) the value is the same object as we are inserting anyway and has its identity set
        if (inserted || !ec.isInserting(value) || (!hasDatastoreAttributedPrimaryKeyValues && (this.mmd != null && this.mmd.isPrimaryKey())) || (!hasDatastoreAttributedPrimaryKeyValues && ownerOP == valueOP && api.getIdForObject(value) != null)) {
            // The PC is either already inserted, or inserted down to the level we need, or not inserted at all,
            // or the field is a PK and identity not attributed by the datastore
            // Object either already exists, or is not yet being inserted.
            id = api.getIdForObject(value);
            // Check if the persistable object exists in this datastore
            boolean requiresPersisting = false;
            if (ec.getApiAdapter().isDetached(value) && ownerOP != null) {
                // Detached object so needs attaching
                if (ownerOP.isInserting()) {
                    // we can just return the value now and attach later (in InsertRequest)
                    if (!ec.getBooleanProperty(PropertyNames.PROPERTY_ATTACH_SAME_DATASTORE)) {
                        if (ec.getObjectFromCache(api.getIdForObject(value)) != null) {
                        // Object is in cache so exists for this datastore, so no point checking
                        } else {
                            try {
                                Object obj = ec.findObject(api.getIdForObject(value), true, false, value.getClass().getName());
                                if (obj != null) {
                                    // Make sure this object is not retained in cache etc
                                    ObjectProvider objOP = ec.findObjectProvider(obj);
                                    if (objOP != null) {
                                        ec.evictFromTransaction(objOP);
                                    }
                                    ec.removeObjectFromLevel1Cache(api.getIdForObject(value));
                                }
                            } catch (NucleusObjectNotFoundException onfe) {
                                // Object doesn't yet exist
                                requiresPersisting = true;
                            }
                        }
                    }
                } else {
                    requiresPersisting = true;
                }
            } else if (id == null) {
                // Transient object, so we need to persist it
                requiresPersisting = true;
            } else {
                ExecutionContext pcEC = ec.getApiAdapter().getExecutionContext(value);
                if (pcEC != null && ec != pcEC) {
                    throw new NucleusUserException(Localiser.msg("041015"), id);
                }
            }
            if (requiresPersisting) {
                // This PC object needs persisting (new or detached) to do the "set"
                if (mmd != null && !mmd.isCascadePersist() && !ec.getApiAdapter().isDetached(value)) {
                    // Related PC object not persistent, but cant do cascade-persist so throw exception
                    if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                        NucleusLogger.PERSISTENCE.debug(Localiser.msg("007006", mmd.getFullFieldName()));
                    }
                    throw new ReachableObjectNotCascadedException(mmd.getFullFieldName(), value);
                }
                if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                    NucleusLogger.PERSISTENCE.debug(Localiser.msg("007007", mmd != null ? mmd.getFullFieldName() : null));
                }
                try {
                    Object pcNew = ec.persistObjectInternal(value, null, -1, ObjectProvider.PC);
                    if (hasDatastoreAttributedPrimaryKeyValues) {
                        ec.flushInternal(false);
                    }
                    id = api.getIdForObject(pcNew);
                    if (ec.getApiAdapter().isDetached(value) && ownerOP != null && mmd != null) {
                        // Update any detached reference to refer to the attached variant
                        ownerOP.replaceFieldMakeDirty(ownerFieldNumber, pcNew);
                        RelationType relationType = mmd.getRelationType(clr);
                        if (relationType == RelationType.MANY_TO_ONE_BI) {
                            // TODO Update the container to refer to the attached object
                            if (NucleusLogger.PERSISTENCE.isInfoEnabled()) {
                                NucleusLogger.PERSISTENCE.info("PCMapping.setObject : object " + ownerOP.getInternalObjectId() + " has field " + ownerFieldNumber + " that is 1-N bidirectional." + " Have just attached the N side so should really update the reference in the 1 side collection" + " to refer to this attached object. Not yet implemented");
                            }
                        } else if (relationType == RelationType.ONE_TO_ONE_BI) {
                            AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
                            // TODO Cater for more than 1 related field
                            ObjectProvider relatedOP = ec.findObjectProvider(pcNew);
                            relatedOP.replaceFieldMakeDirty(relatedMmds[0].getAbsoluteFieldNumber(), ownerOP.getObject());
                        }
                    }
                } catch (NotYetFlushedException e) {
                    setObjectAsNull(ec, ps, param);
                    throw new NotYetFlushedException(value);
                }
            }
            if (valueOP != null) {
                valueOP.setStoringPC();
            }
            // If the field doesn't map to any datastore fields (e.g remote FK), omit the set process
            if (getNumberOfDatastoreMappings() > 0) {
                if (IdentityUtils.isDatastoreIdentity(id)) {
                    Object idKey = IdentityUtils.getTargetKeyForDatastoreIdentity(id);
                    try {
                        // Try as a Long
                        getDatastoreMapping(0).setObject(ps, param[0], idKey);
                    } catch (Exception e) {
                        // Must be a String
                        getDatastoreMapping(0).setObject(ps, param[0], idKey.toString());
                    }
                } else {
                    boolean fieldsSet = false;
                    if (IdentityUtils.isSingleFieldIdentity(id) && javaTypeMappings.length > 1) {
                        Object key = IdentityUtils.getTargetKeyForSingleFieldIdentity(id);
                        AbstractClassMetaData keyCmd = ec.getMetaDataManager().getMetaDataForClass(key.getClass(), clr);
                        if (keyCmd != null && keyCmd.getIdentityType() == IdentityType.NONDURABLE) {
                            // Embedded ID - Make sure these are called starting at lowest first, in order
                            // We cannot just call OP.provideFields with all fields since that does last first
                            ObjectProvider keyOP = ec.findObjectProvider(key);
                            int[] fieldNums = keyCmd.getAllMemberPositions();
                            FieldManager fm = new AppIDObjectIdFieldManager(param, ec, ps, javaTypeMappings);
                            for (int i = 0; i < fieldNums.length; i++) {
                                keyOP.provideFields(new int[] { fieldNums[i] }, fm);
                            }
                            fieldsSet = true;
                        }
                    }
                    if (!fieldsSet) {
                        // Copy PK fields from identity to the object
                        FieldManager fm = new AppIDObjectIdFieldManager(param, ec, ps, javaTypeMappings);
                        api.copyKeyFieldsFromIdToObject(value, new AppIdObjectIdFieldConsumer(api, fm), id);
                    }
                }
            }
        } else {
            if (valueOP != null) {
                valueOP.setStoringPC();
            }
            if (getNumberOfDatastoreMappings() > 0) {
                // Object is in the process of being inserted so we cant use its id currently and we need to store
                // a foreign key to it (which we cant yet do). Just put "null" in and throw "NotYetFlushedException",
                // to be caught by ParameterSetter and will signal to the PC object being inserted that it needs
                // to inform this object when it is inserted.
                setObjectAsNull(ec, ps, param);
                throw new NotYetFlushedException(value);
            }
        }
    } finally {
        if (valueOP != null) {
            valueOP.unsetStoringPC();
        }
    }
}
Also used : ApiAdapter(org.datanucleus.api.ApiAdapter) AppIDObjectIdFieldManager(org.datanucleus.store.rdbms.mapping.AppIDObjectIdFieldManager) SingleValueFieldManager(org.datanucleus.store.fieldmanager.SingleValueFieldManager) FieldManager(org.datanucleus.store.fieldmanager.FieldManager) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) NotYetFlushedException(org.datanucleus.exceptions.NotYetFlushedException) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) ReachableObjectNotCascadedException(org.datanucleus.exceptions.ReachableObjectNotCascadedException) NucleusException(org.datanucleus.exceptions.NucleusException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) NotYetFlushedException(org.datanucleus.exceptions.NotYetFlushedException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ReachableObjectNotCascadedException(org.datanucleus.exceptions.ReachableObjectNotCascadedException) ExecutionContext(org.datanucleus.ExecutionContext) RelationType(org.datanucleus.metadata.RelationType) AppIDObjectIdFieldManager(org.datanucleus.store.rdbms.mapping.AppIDObjectIdFieldManager) ObjectProvider(org.datanucleus.state.ObjectProvider) NucleusException(org.datanucleus.exceptions.NucleusException) AppIdObjectIdFieldConsumer(org.datanucleus.state.AppIdObjectIdFieldConsumer)

Example 3 with FieldManager

use of org.datanucleus.store.fieldmanager.FieldManager in project datanucleus-rdbms by datanucleus.

the class UpdateRequest method execute.

/**
 * Method performing the update of the record in the datastore.
 * Takes the constructed update query and populates with the specific record information.
 * @param op The ObjectProvider for the record to be updated
 */
public void execute(ObjectProvider op) {
    // Choose the statement based on whether optimistic or not
    String stmt = null;
    ExecutionContext ec = op.getExecutionContext();
    boolean optimisticChecks = (versionMetaData != null && ec.getTransaction().getOptimistic() && versionChecks);
    stmt = optimisticChecks ? updateStmtOptimistic : updateStmt;
    if (stmt != null) {
        // TODO Support surrogate update user/timestamp
        AbstractMemberMetaData[] mmds = cmd.getManagedMembers();
        for (int i = 0; i < mmds.length; i++) {
            if (// TODO Make this accessible from cmd
            mmds[i].isUpdateTimestamp()) {
                op.replaceField(mmds[i].getAbsoluteFieldNumber(), new Timestamp(ec.getTransaction().getIsActive() ? ec.getTransaction().getBeginTime() : System.currentTimeMillis()));
            } else if (// TODO Make this accessible from cmd
            mmds[i].isUpdateUser()) {
                op.replaceField(mmds[i].getAbsoluteFieldNumber(), ec.getNucleusContext().getCurrentUser(ec));
            }
        }
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            // Debug info about fields being updated
            StringBuilder fieldStr = new StringBuilder();
            if (updateFieldNumbers != null) {
                for (int i = 0; i < updateFieldNumbers.length; i++) {
                    if (fieldStr.length() > 0) {
                        fieldStr.append(",");
                    }
                    fieldStr.append(cmd.getMetaDataForManagedMemberAtAbsolutePosition(updateFieldNumbers[i]).getName());
                }
            }
            if (versionMetaData != null && versionMetaData.getFieldName() == null) {
                if (fieldStr.length() > 0) {
                    fieldStr.append(",");
                }
                fieldStr.append("[VERSION]");
            }
            // Debug information about what we are updating
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("052214", op.getObjectAsPrintable(), fieldStr.toString(), table));
        }
        RDBMSStoreManager storeMgr = table.getStoreManager();
        boolean batch = false;
        // TODO Set the batch flag based on whether we have no other SQL being invoked in here just our UPDATE
        try {
            ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
            SQLController sqlControl = storeMgr.getSQLController();
            try {
                // Perform the update
                PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, stmt, batch);
                try {
                    Object currentVersion = op.getTransactionalVersion();
                    Object nextVersion = null;
                    if (// TODO What if strategy is NONE?
                    versionMetaData != null) {
                        // Set the next version in the object
                        if (versionMetaData.getFieldName() != null) {
                            // Version field
                            AbstractMemberMetaData verfmd = cmd.getMetaDataForMember(table.getVersionMetaData().getFieldName());
                            if (currentVersion instanceof Number) {
                                // Cater for Integer-based versions
                                currentVersion = Long.valueOf(((Number) currentVersion).longValue());
                            }
                            nextVersion = ec.getLockManager().getNextVersion(versionMetaData, currentVersion);
                            if (verfmd.getType() == Integer.class || verfmd.getType() == int.class) {
                                // Cater for Integer-based versions
                                nextVersion = Integer.valueOf(((Number) nextVersion).intValue());
                            }
                            op.replaceField(verfmd.getAbsoluteFieldNumber(), nextVersion);
                        } else {
                            // Surrogate version column
                            nextVersion = ec.getLockManager().getNextVersion(versionMetaData, currentVersion);
                        }
                        op.setTransactionalVersion(nextVersion);
                    }
                    // SELECT clause - set the required fields to be updated
                    if (updateFieldNumbers != null) {
                        StatementClassMapping mappingDefinition = new StatementClassMapping();
                        StatementMappingIndex[] idxs = stmtMappingDefinition.getUpdateFields();
                        for (int i = 0; i < idxs.length; i++) {
                            if (idxs[i] != null) {
                                mappingDefinition.addMappingForMember(i, idxs[i]);
                            }
                        }
                        op.provideFields(updateFieldNumbers, new ParameterSetter(op, ps, mappingDefinition));
                    }
                    if (versionMetaData != null && versionMetaData.getFieldName() == null) {
                        // SELECT clause - set the surrogate version column to the new version
                        StatementMappingIndex mapIdx = stmtMappingDefinition.getUpdateVersion();
                        for (int i = 0; i < mapIdx.getNumberOfParameterOccurrences(); i++) {
                            table.getSurrogateMapping(SurrogateColumnType.VERSION, false).setObject(ec, ps, mapIdx.getParameterPositionsForOccurrence(i), nextVersion);
                        }
                    }
                    // WHERE clause - primary key fields
                    if (table.getIdentityType() == IdentityType.DATASTORE) {
                        // a). datastore identity
                        StatementMappingIndex mapIdx = stmtMappingDefinition.getWhereDatastoreId();
                        for (int i = 0; i < mapIdx.getNumberOfParameterOccurrences(); i++) {
                            table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, mapIdx.getParameterPositionsForOccurrence(i), op.getInternalObjectId());
                        }
                    } else {
                        // b). application/nondurable identity
                        StatementClassMapping mappingDefinition = new StatementClassMapping();
                        StatementMappingIndex[] idxs = stmtMappingDefinition.getWhereFields();
                        for (int i = 0; i < idxs.length; i++) {
                            if (idxs[i] != null) {
                                mappingDefinition.addMappingForMember(i, idxs[i]);
                            }
                        }
                        FieldManager fm = null;
                        if (cmd.getIdentityType() == IdentityType.NONDURABLE) {
                            fm = new OldValueParameterSetter(op, ps, mappingDefinition);
                        } else {
                            fm = new ParameterSetter(op, ps, mappingDefinition);
                        }
                        op.provideFields(whereFieldNumbers, fm);
                    }
                    if (optimisticChecks) {
                        if (currentVersion == null) {
                            // Somehow the version is not set on this object (not read in ?) so report the bug
                            String msg = Localiser.msg("052201", op.getInternalObjectId(), table);
                            NucleusLogger.PERSISTENCE.error(msg);
                            throw new NucleusException(msg);
                        }
                        // WHERE clause - current version discriminator
                        StatementMappingIndex mapIdx = stmtMappingDefinition.getWhereVersion();
                        for (int i = 0; i < mapIdx.getNumberOfParameterOccurrences(); i++) {
                            mapIdx.getMapping().setObject(ec, ps, mapIdx.getParameterPositionsForOccurrence(i), currentVersion);
                        }
                    }
                    int[] rcs = sqlControl.executeStatementUpdate(ec, mconn, stmt, ps, !batch);
                    if (rcs[0] == 0 && optimisticChecks) {
                        // TODO Batching : when we use batching here we need to process these somehow
                        throw new NucleusOptimisticException(Localiser.msg("052203", op.getObjectAsPrintable(), op.getInternalObjectId(), "" + currentVersion), op.getObject());
                    }
                } finally {
                    sqlControl.closeStatement(mconn, ps);
                }
            } finally {
                mconn.release();
            }
        } catch (SQLException e) {
            String msg = Localiser.msg("052215", op.getObjectAsPrintable(), stmt, StringUtils.getStringFromStackTrace(e));
            NucleusLogger.DATASTORE_PERSIST.error(msg);
            List exceptions = new ArrayList();
            exceptions.add(e);
            while ((e = e.getNextException()) != null) {
                exceptions.add(e);
            }
            throw new NucleusDataStoreException(msg, (Throwable[]) exceptions.toArray(new Throwable[exceptions.size()]));
        }
    }
    // Execute any mapping actions now that we have done the update
    for (int i = 0; i < callbacks.length; ++i) {
        try {
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("052216", op.getObjectAsPrintable(), ((JavaTypeMapping) callbacks[i]).getMemberMetaData().getFullFieldName()));
            }
            callbacks[i].postUpdate(op);
        } catch (NotYetFlushedException e) {
            op.updateFieldAfterInsert(e.getPersistable(), ((JavaTypeMapping) callbacks[i]).getMemberMetaData().getAbsoluteFieldNumber());
        }
    }
}
Also used : FieldManager(org.datanucleus.store.fieldmanager.FieldManager) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) ParameterSetter(org.datanucleus.store.rdbms.fieldmanager.ParameterSetter) OldValueParameterSetter(org.datanucleus.store.rdbms.fieldmanager.OldValueParameterSetter) Timestamp(java.sql.Timestamp) SQLController(org.datanucleus.store.rdbms.SQLController) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) ArrayList(java.util.ArrayList) List(java.util.List) PreparedStatement(java.sql.PreparedStatement) NotYetFlushedException(org.datanucleus.exceptions.NotYetFlushedException) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) ExecutionContext(org.datanucleus.ExecutionContext) NucleusOptimisticException(org.datanucleus.exceptions.NucleusOptimisticException) OldValueParameterSetter(org.datanucleus.store.rdbms.fieldmanager.OldValueParameterSetter) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 4 with FieldManager

use of org.datanucleus.store.fieldmanager.FieldManager in project datanucleus-rdbms by datanucleus.

the class MappingHelper method getObjectForApplicationIdentity.

/**
 * Get the persistent object instance for a class using application identity defined by the provided result set columns
 * @param ec ExecutionContext
 * @param mapping The mapping in which this is returned
 * @param rs the ResultSet
 * @param resultIndexes indexes in the result set to retrieve
 * @param cmd the AbstractClassMetaData
 * @return the persistent object instance
 */
public static Object getObjectForApplicationIdentity(final ExecutionContext ec, JavaTypeMapping mapping, final ResultSet rs, int[] resultIndexes, AbstractClassMetaData cmd) {
    ClassLoaderResolver clr = ec.getClassLoaderResolver();
    // Abstract class
    if (cmd instanceof ClassMetaData && ((ClassMetaData) cmd).isAbstract() && cmd.getObjectidClass() != null) {
        return getObjectForAbstractClass(ec, mapping, rs, resultIndexes, cmd);
    }
    // Create a ResultSetGetter with the data for the primary key column(s) of this class solely
    int totalMemberCount = cmd.getNoOfManagedMembers() + cmd.getNoOfInheritedManagedMembers();
    final StatementMappingIndex[] statementExpressionIndex = new StatementMappingIndex[totalMemberCount];
    DatastoreClass datastoreClass = mapping.getStoreManager().getDatastoreClass(cmd.getFullClassName(), clr);
    final int[] pkMemberPositions = cmd.getPKMemberPositions();
    int paramIndex = 0;
    for (int i = 0; i < pkMemberPositions.length; ++i) {
        AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkMemberPositions[i]);
        JavaTypeMapping m = datastoreClass.getMemberMapping(mmd);
        statementExpressionIndex[mmd.getAbsoluteFieldNumber()] = new StatementMappingIndex(m);
        int[] expressionsIndex = new int[m.getNumberOfColumnMappings()];
        for (int j = 0; j < expressionsIndex.length; j++) {
            expressionsIndex[j] = resultIndexes[paramIndex++];
        }
        statementExpressionIndex[mmd.getAbsoluteFieldNumber()].setColumnPositions(expressionsIndex);
    }
    final StatementClassMapping resultMappings = new StatementClassMapping();
    for (int i = 0; i < pkMemberPositions.length; i++) {
        resultMappings.addMappingForMember(pkMemberPositions[i], statementExpressionIndex[pkMemberPositions[i]]);
    }
    // TODO Use any other (non-PK) param values
    final FieldManager resultsFM = new ResultSetGetter(ec, rs, resultMappings, cmd);
    Object id = IdentityUtils.getApplicationIdentityForResultSetRow(ec, cmd, null, false, resultsFM);
    Class type = ec.getClassLoaderResolver().classForName(cmd.getFullClassName());
    return ec.findObject(id, new FieldValues() {

        public void fetchFields(DNStateManager sm) {
            sm.replaceFields(pkMemberPositions, resultsFM);
        }

        public void fetchNonLoadedFields(DNStateManager sm) {
            sm.replaceNonLoadedFields(pkMemberPositions, resultsFM);
        }

        public FetchPlan getFetchPlanForLoading() {
            return ec.getFetchPlan();
        }
    }, type, false, true);
}
Also used : FieldManager(org.datanucleus.store.fieldmanager.FieldManager) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) FetchPlan(org.datanucleus.FetchPlan) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) ResultSetGetter(org.datanucleus.store.rdbms.fieldmanager.ResultSetGetter) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DNStateManager(org.datanucleus.state.DNStateManager) FieldValues(org.datanucleus.store.FieldValues) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ClassMetaData(org.datanucleus.metadata.ClassMetaData)

Example 5 with FieldManager

use of org.datanucleus.store.fieldmanager.FieldManager in project datanucleus-rdbms by datanucleus.

the class PersistableMapping method getValueForColumnMapping.

/**
 * 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 getValueForColumnMapping(NucleusContext nucleusCtx, int index, Object value) {
    ExecutionContext ec = nucleusCtx.getApiAdapter().getExecutionContext(value);
    if (cmd.getIdentityType() == IdentityType.APPLICATION) {
        AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(cmd.getPKMemberPositions()[index]);
        DNStateManager sm = null;
        if (ec != null) {
            sm = ec.findStateManager(value);
        }
        if (sm == null) {
            // Transient or detached maybe, so use reflection to get PK field values
            return (mmd instanceof FieldMetaData) ? ClassUtils.getValueOfFieldByReflection(value, mmd.getName()) : ClassUtils.getValueOfMethodByReflection(value, ClassUtils.getJavaBeanGetterName(mmd.getName(), false));
        }
        if (!mmd.isPrimaryKey()) {
            // Make sure the field is loaded
            sm.isLoaded(mmd.getAbsoluteFieldNumber());
        }
        FieldManager fm = new SingleValueFieldManager();
        sm.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) DNStateManager(org.datanucleus.state.DNStateManager) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

FieldManager (org.datanucleus.store.fieldmanager.FieldManager)18 SingleValueFieldManager (org.datanucleus.store.fieldmanager.SingleValueFieldManager)12 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)9 ExecutionContext (org.datanucleus.ExecutionContext)8 L2CachePopulateFieldManager (org.datanucleus.cache.L2CachePopulateFieldManager)7 L2CacheRetrieveFieldManager (org.datanucleus.cache.L2CacheRetrieveFieldManager)7 AttachFieldManager (org.datanucleus.store.fieldmanager.AttachFieldManager)7 DeleteFieldManager (org.datanucleus.store.fieldmanager.DeleteFieldManager)7 DetachFieldManager (org.datanucleus.store.fieldmanager.DetachFieldManager)7 LoadFieldManager (org.datanucleus.store.fieldmanager.LoadFieldManager)7 MakeTransientFieldManager (org.datanucleus.store.fieldmanager.MakeTransientFieldManager)7 PersistFieldManager (org.datanucleus.store.fieldmanager.PersistFieldManager)7 SingleTypeFieldManager (org.datanucleus.store.fieldmanager.SingleTypeFieldManager)7 UnsetOwnerFieldManager (org.datanucleus.store.fieldmanager.UnsetOwnerFieldManager)7 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)6 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)5 DNStateManager (org.datanucleus.state.DNStateManager)5 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)5 ArrayList (java.util.ArrayList)4 NotYetFlushedException (org.datanucleus.exceptions.NotYetFlushedException)4