Search in sources :

Example 51 with DNStateManager

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

the class BackingStoreHelper method populateEmbeddedValueFieldsInStatement.

/**
 * Convenience method to populate the passed PreparedStatement with the field values from
 * the embedded map value starting at the specified jdbc position.
 * @param sm StateManager of the owning container
 * @param value The embedded value
 * @param ps The PreparedStatement
 * @param jdbcPosition JDBC position in the statement to start at
 * @param joinTable The Join table where the values are embedded
 * @param mapStore The map store
 * @return The next JDBC position
 */
public static int populateEmbeddedValueFieldsInStatement(DNStateManager sm, Object value, PreparedStatement ps, int jdbcPosition, JoinTable joinTable, AbstractMapStore mapStore) {
    AbstractClassMetaData vmd = mapStore.getValueClassMetaData();
    EmbeddedValuePCMapping embeddedMapping = (EmbeddedValuePCMapping) mapStore.getValueMapping();
    StatementClassMapping mappingDefinition = new StatementClassMapping();
    int[] elementFieldNumbers = new int[embeddedMapping.getNumberOfJavaTypeMappings()];
    for (int i = 0; i < embeddedMapping.getNumberOfJavaTypeMappings(); i++) {
        JavaTypeMapping fieldMapping = embeddedMapping.getJavaTypeMapping(i);
        int absFieldNum = vmd.getAbsolutePositionOfMember(fieldMapping.getMemberMetaData().getName());
        elementFieldNumbers[i] = absFieldNum;
        StatementMappingIndex stmtMapping = new StatementMappingIndex(fieldMapping);
        int[] jdbcParamPositions = new int[fieldMapping.getNumberOfColumnMappings()];
        for (int j = 0; j < fieldMapping.getNumberOfColumnMappings(); j++) {
            jdbcParamPositions[j] = jdbcPosition++;
        }
        stmtMapping.addParameterOccurrence(jdbcParamPositions);
        mappingDefinition.addMappingForMember(absFieldNum, stmtMapping);
    }
    DNStateManager elementSM = mapStore.getStateManagerForEmbeddedPCObject(sm, value, joinTable.getOwnerMemberMetaData(), PersistableObjectType.EMBEDDED_MAP_VALUE_PC);
    elementSM.provideFields(elementFieldNumbers, new ParameterSetter(elementSM, ps, mappingDefinition));
    return jdbcPosition;
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) EmbeddedValuePCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedValuePCMapping) DNStateManager(org.datanucleus.state.DNStateManager) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) ParameterSetter(org.datanucleus.store.rdbms.fieldmanager.ParameterSetter) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping)

Example 52 with DNStateManager

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

the class BackingStoreHelper method populateOwnerInStatement.

/**
 * Convenience method to populate the passed PreparedStatement with the value from the owner.
 * @param sm StateManager
 * @param ec execution context
 * @param ps The PreparedStatement
 * @param jdbcPosition Position in JDBC statement to populate
 * @param bcs Base container backing store
 * @return The next position in the JDBC statement
 */
public static int populateOwnerInStatement(DNStateManager sm, ExecutionContext ec, PreparedStatement ps, int jdbcPosition, BaseContainerStore bcs) {
    // Find the real owner in case the provide object is embedded
    boolean embedded = false;
    DNStateManager ownerSM = getOwnerStateManagerForBackingStore(sm);
    if (ownerSM != sm) {
        embedded = true;
    }
    if (!bcs.getOwnerMapping().getColumnMapping(0).insertValuesOnInsert()) {
        // Don't try to insert any mappings with insert parameter that isnt ? (e.g Oracle)
        return jdbcPosition;
    }
    if (bcs.getOwnerMemberMetaData() != null && !embedded) {
        bcs.getOwnerMapping().setObject(ec, ps, MappingHelper.getMappingIndices(jdbcPosition, bcs.getOwnerMapping()), ownerSM.getObject(), ownerSM, bcs.getOwnerMemberMetaData().getAbsoluteFieldNumber());
    } else {
        // Either we have no member info, or we are setting the owner when the provided owner is embedded, so are navigating back to the real owner
        bcs.getOwnerMapping().setObject(ec, ps, MappingHelper.getMappingIndices(jdbcPosition, bcs.getOwnerMapping()), ownerSM.getObject());
    }
    return jdbcPosition + bcs.getOwnerMapping().getNumberOfColumnMappings();
}
Also used : DNStateManager(org.datanucleus.state.DNStateManager)

Example 53 with DNStateManager

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

the class FKMapStore method removeValue.

/**
 * Utility to remove a value from the Map.
 * @param sm StateManager for the map.
 * @param key Key of the object
 * @param oldValue Value to remove
 */
private void removeValue(DNStateManager sm, Object key, Object oldValue) {
    ExecutionContext ec = sm.getExecutionContext();
    // Null out the key and owner fields if they are nullable
    if (keyMapping.isNullable()) {
        DNStateManager vsm = ec.findStateManager(oldValue);
        // Null the key field
        vsm.replaceFieldMakeDirty(keyFieldNumber, null);
        if (ec.getManageRelations()) {
            ec.getRelationshipManager(vsm).relationChange(keyFieldNumber, key, null);
        }
        // Null the owner field
        if (ownerFieldNumber >= 0) {
            Object oldOwner = vsm.provideField(ownerFieldNumber);
            vsm.replaceFieldMakeDirty(ownerFieldNumber, null);
            if (ec.getManageRelations()) {
                ec.getRelationshipManager(vsm).relationChange(ownerFieldNumber, oldOwner, null);
            }
        } else {
            updateValueFk(sm, oldValue, null);
        }
    } else // otherwise just delete the item
    {
        ec.deleteObjectInternal(oldValue);
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) DNStateManager(org.datanucleus.state.DNStateManager)

Example 54 with DNStateManager

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

the class FKMapStore method put.

@Override
public V put(final DNStateManager sm, final K newKey, V newValue) {
    ExecutionContext ec = sm.getExecutionContext();
    if (keyFieldNumber >= 0) {
        validateKeyForWriting(sm, newKey);
        validateValueType(ec.getClassLoaderResolver(), newValue);
    } else {
        validateKeyType(ec.getClassLoaderResolver(), newKey);
        validateValueForWriting(sm, newValue);
    }
    // Check if there is an existing value for this key
    V oldValue = get(sm, newKey);
    if (oldValue != newValue) {
        if (valueCmd != null) {
            if (oldValue != null && !oldValue.equals(newValue)) {
                // Key is stored in the value and the value has changed so remove the old value
                removeValue(sm, newKey, oldValue);
            }
            final Object newOwner = sm.getObject();
            if (ec.getApiAdapter().isPersistent(newValue)) {
                /*
                     * The new value is already persistent.
                     *
                     * "Put" the new value in the map by updating its owner and key
                     * fields to the appropriate values.  This is done with the same
                     * methods the PC itself would use if the application code
                     * modified the fields.  It should result in no actual database
                     * activity if the fields were already set to the right values.
                     */
                if (ec != ec.getApiAdapter().getExecutionContext(newValue)) {
                    throw new NucleusUserException(Localiser.msg("RDBMS.SCO.Map.WriteValueInvalidWithDifferentPM"), ec.getApiAdapter().getIdForObject(newValue));
                }
                DNStateManager vsm = ec.findStateManager(newValue);
                // Ensure the current owner field is loaded, and replace with new value
                if (ownerFieldNumber >= 0) {
                    vsm.isLoaded(ownerFieldNumber);
                    Object oldOwner = vsm.provideField(ownerFieldNumber);
                    vsm.replaceFieldMakeDirty(ownerFieldNumber, newOwner);
                    if (ec.getManageRelations()) {
                        ec.getRelationshipManager(vsm).relationChange(ownerFieldNumber, oldOwner, newOwner);
                    }
                } else {
                    updateValueFk(sm, newValue, newOwner);
                }
                // Ensure the current key field is loaded, and replace with new value
                vsm.isLoaded(keyFieldNumber);
                Object oldKey = vsm.provideField(keyFieldNumber);
                vsm.replaceFieldMakeDirty(keyFieldNumber, newKey);
                if (ec.getManageRelations()) {
                    ec.getRelationshipManager(vsm).relationChange(keyFieldNumber, oldKey, newKey);
                }
            } else {
                /*
                     * The new value is not yet persistent.
                     *
                     * Update its owner and key fields to the appropriate values and
                     * *then* make it persistent.  Making the changes before DB
                     * insertion avoids an unnecessary UPDATE allows the owner
                     * and/or key fields to be non-nullable.
                     */
                ec.persistObjectInternal(newValue, new FieldValues() {

                    public void fetchFields(DNStateManager vsm) {
                        if (ownerFieldNumber >= 0) {
                            vsm.replaceFieldMakeDirty(ownerFieldNumber, newOwner);
                        }
                        vsm.replaceFieldMakeDirty(keyFieldNumber, newKey);
                        JavaTypeMapping externalFKMapping = mapTable.getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_FK);
                        if (externalFKMapping != null) {
                            // Set the owner in the value object where appropriate
                            vsm.setAssociatedValue(externalFKMapping, sm.getObject());
                        }
                    }

                    public void fetchNonLoadedFields(DNStateManager sm) {
                    }

                    public FetchPlan getFetchPlanForLoading() {
                        return null;
                    }
                }, PersistableObjectType.PC);
            }
        } else {
            // Value is stored in the key
            final Object newOwner = sm.getObject();
            if (ec.getApiAdapter().isPersistent(newKey)) {
                /*
                     * The new key is already persistent.
                     *
                     * "Put" the new key in the map by updating its owner and value
                     * fields to the appropriate values. This is done with the same
                     * methods the PC itself would use if the application code
                     * modified the fields. It should result in no actual database
                     * activity if the fields were already set to the right values.
                     */
                if (ec != ec.getApiAdapter().getExecutionContext(newKey)) {
                    throw new NucleusUserException(Localiser.msg("056060"), ec.getApiAdapter().getIdForObject(newKey));
                }
                DNStateManager valSM = ec.findStateManager(newKey);
                // Ensure the current owner field is loaded, and replace with new key
                if (ownerFieldNumber >= 0) {
                    valSM.isLoaded(ownerFieldNumber);
                    Object oldOwner = valSM.provideField(ownerFieldNumber);
                    valSM.replaceFieldMakeDirty(ownerFieldNumber, newOwner);
                    if (ec.getManageRelations()) {
                        ec.getRelationshipManager(valSM).relationChange(ownerFieldNumber, oldOwner, newOwner);
                    }
                } else {
                    updateKeyFk(sm, newKey, newOwner);
                }
                // Ensure the current value field is loaded, and replace with new value
                valSM.isLoaded(valueFieldNumber);
                // TODO Should we update the local variable ?
                oldValue = (V) valSM.provideField(valueFieldNumber);
                valSM.replaceFieldMakeDirty(valueFieldNumber, newValue);
                if (ec.getManageRelations()) {
                    ec.getRelationshipManager(valSM).relationChange(valueFieldNumber, oldValue, newValue);
                }
            } else {
                /*
                     * The new key is not yet persistent.
                     *
                     * Update its owner and key fields to the appropriate values and
                     * *then* make it persistent.  Making the changes before DB
                     * insertion avoids an unnecessary UPDATE allows the owner
                     * and/or key fields to be non-nullable.
                     */
                final Object newValueObj = newValue;
                ec.persistObjectInternal(newKey, new FieldValues() {

                    public void fetchFields(DNStateManager vsm) {
                        if (ownerFieldNumber >= 0) {
                            vsm.replaceFieldMakeDirty(ownerFieldNumber, newOwner);
                        }
                        vsm.replaceFieldMakeDirty(valueFieldNumber, newValueObj);
                        JavaTypeMapping externalFKMapping = mapTable.getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_FK);
                        if (externalFKMapping != null) {
                            // Set the owner in the value object where appropriate
                            vsm.setAssociatedValue(externalFKMapping, sm.getObject());
                        }
                    }

                    public void fetchNonLoadedFields(DNStateManager sm) {
                    }

                    public FetchPlan getFetchPlanForLoading() {
                        return null;
                    }
                }, PersistableObjectType.PC);
            /*if (ownerFieldNumber < 0)
                    {
                        // TODO Think about removing this since we set the associated owner here
                        updateKeyFk(sm, newKey, newOwner);
                    }*/
            }
        }
    }
    // TODO Cater for key being PC and having delete-dependent
    if (ownerMemberMetaData.getMap().isDependentValue() && oldValue != null) {
        // Delete the old value if it is no longer contained and is dependent
        if (!containsValue(sm, oldValue)) {
            ec.deleteObjectInternal(oldValue);
        }
    }
    return oldValue;
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) DNStateManager(org.datanucleus.state.DNStateManager) FieldValues(org.datanucleus.store.FieldValues) FetchPlan(org.datanucleus.FetchPlan)

Example 55 with DNStateManager

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

the class JoinSetStore method add.

@Override
public boolean add(DNStateManager sm, E element, int size) {
    // Check that the object is valid for writing
    ExecutionContext ec = sm.getExecutionContext();
    validateElementForWriting(ec, element, null);
    if (relationType == RelationType.ONE_TO_MANY_BI) {
        // TODO This is ManagedRelations - move into RelationshipManager
        // Managed Relations : make sure we have consistency of relation
        DNStateManager elementSM = ec.findStateManager(element);
        if (elementSM != null) {
            AbstractMemberMetaData[] relatedMmds = ownerMemberMetaData.getRelatedMemberMetaData(clr);
            Object elementOwner = elementSM.provideField(relatedMmds[0].getAbsoluteFieldNumber());
            if (elementOwner == null) {
                // No owner, so correct it
                NucleusLogger.PERSISTENCE.info(Localiser.msg("056037", sm.getObjectAsPrintable(), ownerMemberMetaData.getFullFieldName(), StringUtils.toJVMIDString(elementSM.getObject())));
                elementSM.replaceField(relatedMmds[0].getAbsoluteFieldNumber(), sm.getObject());
            } else if (elementOwner != sm.getObject() && sm.getReferencedPC() == null) {
                // Inconsistent owner, so throw exception
                throw new NucleusUserException(Localiser.msg("056038", sm.getObjectAsPrintable(), ownerMemberMetaData.getFullFieldName(), StringUtils.toJVMIDString(elementSM.getObject()), StringUtils.toJVMIDString(elementOwner)));
            }
        }
    }
    boolean modified = false;
    boolean toBeInserted = true;
    if (relationType == RelationType.MANY_TO_MANY_BI) {
        toBeInserted = !elementAlreadyContainsOwnerInMtoN(sm, element);
    }
    if (toBeInserted) {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        try {
            // Add a row to the join table
            int orderID = orderMapping != null ? getNextIDForOrderColumn(sm) : -1;
            int[] returnCode = doInternalAdd(sm, element, mconn, false, orderID, true);
            if (returnCode[0] > 0) {
                modified = true;
            }
        } finally {
            mconn.release();
        }
    }
    return modified;
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) DNStateManager(org.datanucleus.state.DNStateManager) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

DNStateManager (org.datanucleus.state.DNStateManager)64 ExecutionContext (org.datanucleus.ExecutionContext)38 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)22 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)20 SQLException (java.sql.SQLException)17 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)16 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)15 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)15 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)14 StatementClassMapping (org.datanucleus.store.rdbms.query.StatementClassMapping)14 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)13 SQLController (org.datanucleus.store.rdbms.SQLController)13 PreparedStatement (java.sql.PreparedStatement)12 ResultSet (java.sql.ResultSet)10 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)9 NucleusException (org.datanucleus.exceptions.NucleusException)9 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)9 Collection (java.util.Collection)8 ArrayList (java.util.ArrayList)7 RelationType (org.datanucleus.metadata.RelationType)7