Search in sources :

Example 36 with DNStateManager

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

the class MultiPersistableMapping method setObject.

/**
 * Sets the specified positions in the PreparedStatement associated with this field, and value.
 * If the number of positions in "pos" is not the same as the number of datastore mappings then it is assumed
 * that we should only set the positions for the real implementation FK; this happens where we have a statement
 * like "... WHERE IMPL1_ID_OID = ? AND IMPL2_ID_OID IS NULL" so we need to filter on the other implementations
 * being null and only want to input parameter(s) for the real implementation of "value".
 * @param ec execution context
 * @param ps a datastore object that executes statements in the database
 * @param value the value stored in this field
 * @param ownerSM the owner StateManager
 * @param ownerFieldNumber the owner absolute field number
 * @param pos The position(s) of the PreparedStatement to populate
 */
@Override
public void setObject(ExecutionContext ec, PreparedStatement ps, int[] pos, Object value, DNStateManager ownerSM, int ownerFieldNumber) {
    boolean setValueFKOnly = false;
    if (pos != null && pos.length < getNumberOfColumnMappings()) {
        setValueFKOnly = true;
    }
    // Make sure that this field has a sub-mapping appropriate for the specified value
    int javaTypeMappingNumber = getMappingNumberForValue(ec, value);
    if (value != null && javaTypeMappingNumber == -1) {
        // TODO Change this to a multiple field mapping localised message
        throw new ClassCastException(Localiser.msg("041044", mmd != null ? mmd.getFullFieldName() : "", getType(), value.getClass().getName()));
    }
    if (value != null) {
        ApiAdapter api = ec.getApiAdapter();
        ClassLoaderResolver clr = ec.getClassLoaderResolver();
        // Make sure the value is persisted if it is persistable in its own right
        if (!ec.isInserting(value)) {
            // Object either already exists, or is not yet being inserted.
            Object id = api.getIdForObject(value);
            // Check if the persistable exists in this datastore
            boolean requiresPersisting = false;
            if (ec.getApiAdapter().isDetached(value) && ownerSM != null) {
                // Detached object that needs attaching (or persisting if detached from a different datastore)
                requiresPersisting = true;
            } else if (id == null) {
                // Transient object, so we need to persist it
                requiresPersisting = true;
            } else {
                ExecutionContext valueEC = api.getExecutionContext(value);
                if (valueEC != null && ec != valueEC) {
                    throw new NucleusUserException(Localiser.msg("041015"), id);
                }
            }
            if (requiresPersisting) {
                // The object is either not yet persistent or is detached and so needs attaching
                Object pcNew = ec.persistObjectInternal(value, null, -1, PersistableObjectType.PC);
                ec.flushInternal(false);
                id = api.getIdForObject(pcNew);
                if (ec.getApiAdapter().isDetached(value) && ownerSM != null) {
                    // Update any detached reference to refer to the attached variant
                    ownerSM.replaceFieldMakeDirty(ownerFieldNumber, pcNew);
                    if (mmd != null) {
                        RelationType relationType = mmd.getRelationType(clr);
                        if (relationType == RelationType.ONE_TO_ONE_BI) {
                            DNStateManager relatedSM = ec.findStateManager(pcNew);
                            AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
                            // TODO Allow for multiple related fields
                            relatedSM.replaceFieldMakeDirty(relatedMmds[0].getAbsoluteFieldNumber(), ownerSM.getObject());
                        } else if (relationType == RelationType.MANY_TO_ONE_BI) {
                            // TODO Update the container element with the attached variant
                            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                                NucleusLogger.PERSISTENCE.debug("PCMapping.setObject : object " + ownerSM.getInternalObjectId() + " has field " + ownerFieldNumber + " that is 1-N bidirectional - should really update the reference in the relation. Not yet supported");
                            }
                        }
                    }
                }
            }
            if (getNumberOfColumnMappings() <= 0) {
                // If the field doesn't map to any columns, omit the set process
                return;
            }
        }
    }
    if (pos == null) {
        return;
    }
    DNStateManager sm = (value != null ? ec.findStateManager(value) : null);
    try {
        if (sm != null) {
            sm.setStoringPC();
        }
        int n = 0;
        NotYetFlushedException notYetFlushed = null;
        for (int i = 0; i < javaTypeMappings.length; i++) {
            // Set the PreparedStatement positions for this implementation mapping
            int[] posMapping;
            if (setValueFKOnly) {
                // Only using first "pos" value(s)
                n = 0;
            } else if (n >= pos.length) {
                // store all implementations to the same columns, so we reset the index
                n = 0;
            }
            if (javaTypeMappings[i].getReferenceMapping() != null) {
                posMapping = new int[javaTypeMappings[i].getReferenceMapping().getNumberOfColumnMappings()];
            } else {
                posMapping = new int[javaTypeMappings[i].getNumberOfColumnMappings()];
            }
            for (int j = 0; j < posMapping.length; j++) {
                posMapping[j] = pos[n++];
            }
            try {
                if (javaTypeMappingNumber == -2 || (value != null && javaTypeMappingNumber == i)) {
                    // This mapping is where the value is to be stored, or using persistent interfaces
                    javaTypeMappings[i].setObject(ec, ps, posMapping, value);
                } else if (!setValueFKOnly) {
                    // Set null for this mapping, since the value is null or is for something else
                    javaTypeMappings[i].setObject(ec, ps, posMapping, null);
                }
            } catch (NotYetFlushedException e) {
                notYetFlushed = e;
            }
        }
        if (notYetFlushed != null) {
            throw notYetFlushed;
        }
    } finally {
        if (sm != null) {
            sm.unsetStoringPC();
        }
    }
}
Also used : ApiAdapter(org.datanucleus.api.ApiAdapter) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) NotYetFlushedException(org.datanucleus.exceptions.NotYetFlushedException) ExecutionContext(org.datanucleus.ExecutionContext) RelationType(org.datanucleus.metadata.RelationType) DNStateManager(org.datanucleus.state.DNStateManager) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 37 with DNStateManager

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

the class OracleCollectionMapping method postUpdate.

public void postUpdate(DNStateManager ownerSM) {
    if (containerIsStoredInSingleColumn()) {
        ExecutionContext ec = ownerSM.getExecutionContext();
        Collection value = (Collection) ownerSM.provideField(mmd.getAbsoluteFieldNumber());
        if (value != null) {
            if (mmd.getCollection().elementIsPersistent()) {
                // Make sure all persistable elements have StateManagers
                Object[] collElements = value.toArray();
                for (Object elem : collElements) {
                    if (elem != null) {
                        DNStateManager elemSM = ec.findStateManager(elem);
                        if (elemSM == null || ec.getApiAdapter().getExecutionContext(elem) == null) {
                            elemSM = ec.getNucleusContext().getStateManagerFactory().newForEmbedded(ec, elem, false, ownerSM, mmd.getAbsoluteFieldNumber(), PersistableObjectType.EMBEDDED_COLLECTION_ELEMENT_PC);
                        }
                    }
                }
            }
        }
    } else {
        super.postUpdate(ownerSM);
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) DNStateManager(org.datanucleus.state.DNStateManager)

Example 38 with DNStateManager

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

the class OracleCollectionMapping method postInsert.

public void postInsert(DNStateManager ownerSM) {
    if (containerIsStoredInSingleColumn()) {
        ExecutionContext ec = ownerSM.getExecutionContext();
        Collection value = (Collection) ownerSM.provideField(mmd.getAbsoluteFieldNumber());
        if (value != null) {
            if (mmd.getCollection().elementIsPersistent()) {
                // Make sure all persistable elements have StateManagers
                Object[] collElements = value.toArray();
                for (Object elem : collElements) {
                    if (elem != null) {
                        DNStateManager elemSM = ec.findStateManager(elem);
                        if (elemSM == null || ec.getApiAdapter().getExecutionContext(elem) == null) {
                            elemSM = ec.getNucleusContext().getStateManagerFactory().newForEmbedded(ec, elem, false, ownerSM, mmd.getAbsoluteFieldNumber(), PersistableObjectType.EMBEDDED_COLLECTION_ELEMENT_PC);
                        }
                    }
                }
            }
        }
    } else {
        super.postInsert(ownerSM);
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) DNStateManager(org.datanucleus.state.DNStateManager)

Example 39 with DNStateManager

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

the class SerialisedReferenceMapping method setObject.

/**
 * Method to populate parameter positions in a PreparedStatement with this object
 * @param ec execution context
 * @param ps The Prepared Statement
 * @param exprIndex The parameter positions to populate
 * @param value The value of the PC to use in populating the parameter positions
 * @param ownerSM StateManager for the owning object
 * @param fieldNumber field number of this object in the owning object
 */
@Override
public void setObject(ExecutionContext ec, PreparedStatement ps, int[] exprIndex, Object value, DNStateManager ownerSM, int fieldNumber) {
    ApiAdapter api = ec.getApiAdapter();
    if (api.isPersistable(value)) {
        // Assign a StateManager to the serialised object if none present
        DNStateManager embSM = ec.findStateManager(value);
        if (embSM == null || api.getExecutionContext(value) == null) {
            embSM = ec.getNucleusContext().getStateManagerFactory().newForEmbedded(ec, value, false, ownerSM, fieldNumber, PersistableObjectType.EMBEDDED_PC);
        }
    }
    DNStateManager sm = null;
    if (api.isPersistable(value)) {
        // Find SM for serialised PC object
        sm = ec.findStateManager(value);
    }
    if (sm != null) {
        sm.setStoringPC();
    }
    getColumnMapping(0).setObject(ps, exprIndex[0], value);
    if (sm != null) {
        sm.unsetStoringPC();
    }
}
Also used : ApiAdapter(org.datanucleus.api.ApiAdapter) DNStateManager(org.datanucleus.state.DNStateManager)

Example 40 with DNStateManager

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

the class ReferenceMapping method getReferenceStringForObject.

/**
 * Method to convert an object to be stored into a "reference string" to store.
 * Reference string is of the form :
 * <ul>
 * <li>ID_MAPPING : "{classname}:{id}"</li>
 * <li>XCALIA_MAPPING (datastore-id) : "{definer}:{id-key}" where definer is discriminator/classname</li>
 * <li>XCALIA_MAPPING (app-id) : "{definer}:{id}" where definer is discriminator/classname</li>
 * </ul>
 * @param ec ExecutionContext
 * @param value The object
 * @return The reference string
 */
protected String getReferenceStringForObject(ExecutionContext ec, Object value) {
    if (ec.getApiAdapter().isPersistable(value)) {
        DNStateManager sm = ec.findStateManager(value);
        if (sm == null) {
            // Referenced object is not yet persistent, so persist it
            ec.persistObjectInternal(value, null, -1, PersistableObjectType.PC);
            sm = ec.findStateManager(value);
            // Make sure the object is in the datastore so the id is set
            sm.flush();
        }
        String refString = null;
        if (mappingStrategy == ID_MAPPING) {
            refString = value.getClass().getName() + ":" + sm.getInternalObjectId();
        } else if (mappingStrategy == XCALIA_MAPPING) {
            AbstractClassMetaData cmd = sm.getClassMetaData();
            DiscriminatorMetaData dismd = cmd.getDiscriminatorMetaData();
            String definer = null;
            if (dismd != null && dismd.getValue() != null) {
                definer = dismd.getValue();
            } else {
                definer = cmd.getFullClassName();
            }
            if (cmd.getIdentityType() == IdentityType.DATASTORE) {
                refString = definer + ":" + IdentityUtils.getTargetKeyForDatastoreIdentity(sm.getInternalObjectId());
            } else {
                refString = definer + ":" + sm.getInternalObjectId().toString();
            }
        }
        return refString;
    }
    // Cater for non-persistable objects
    throw new NucleusException("Identity mapping of non-persistable interface/Object fields not supported");
}
Also used : DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) DNStateManager(org.datanucleus.state.DNStateManager) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData)

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