Search in sources :

Example 1 with BackedSCO

use of org.datanucleus.store.types.wrappers.backed.BackedSCO in project datanucleus-rdbms by datanucleus.

the class CollectionMapping method postUpdate.

/**
 * Method to be called after any update of the owner class element.
 * This method could be called in two situations
 * <ul>
 * <li>Update a collection field of an object by replacing the collection with a new collection, so UpdateRequest is called, which calls here</li>
 * <li>Persist a new object, and it needed to wait til the element was inserted so goes into dirty state and then flush() triggers UpdateRequest, which comes here</li>
 * </ul>
 * @param ownerOP ObjectProvider of the owner
 */
public void postUpdate(ObjectProvider ownerOP) {
    ExecutionContext ec = ownerOP.getExecutionContext();
    Collection value = (Collection) ownerOP.provideField(getAbsoluteFieldNumber());
    if (containerIsStoredInSingleColumn()) {
        if (value != null) {
            if (mmd.getCollection().elementIsPersistent()) {
                // Make sure all persistable elements have ObjectProviders
                Object[] collElements = value.toArray();
                for (Object collElement : collElements) {
                    if (collElement != null) {
                        ObjectProvider elemOP = ec.findObjectProvider(collElement);
                        if (elemOP == null || ec.getApiAdapter().getExecutionContext(collElement) == null) {
                            elemOP = ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, collElement, false, ownerOP, mmd.getAbsoluteFieldNumber());
                        }
                    }
                }
            }
        }
        return;
    }
    if (value == null) {
        // remove any elements in the collection and replace it with an empty SCO wrapper
        ((CollectionStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null)).clear(ownerOP);
        replaceFieldWithWrapper(ownerOP, null);
        return;
    }
    if (value instanceof BackedSCO) {
        // Already have a SCO value, so flush outstanding updates
        ownerOP.getExecutionContext().flushOperationsForBackingStore(((BackedSCO) value).getBackingStore(), ownerOP);
        return;
    }
    if (mmd.isCascadeUpdate()) {
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007009", mmd.getFullFieldName()));
        }
        CollectionStore backingStore = ((CollectionStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, value.getClass()));
        backingStore.update(ownerOP, value);
        // Replace the field with a wrapper containing these elements
        replaceFieldWithWrapper(ownerOP, value);
    } else {
        // User doesn't want to update by reachability
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007008", mmd.getFullFieldName()));
        }
        return;
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) ObjectProvider(org.datanucleus.state.ObjectProvider) CollectionStore(org.datanucleus.store.types.scostore.CollectionStore) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO)

Example 2 with BackedSCO

use of org.datanucleus.store.types.wrappers.backed.BackedSCO in project datanucleus-rdbms by datanucleus.

the class MapMapping method postUpdate.

/**
 * Method to be called after any update of the owner class element.
 * @param ownerOP ObjectProvider of the owner
 */
public void postUpdate(ObjectProvider ownerOP) {
    ExecutionContext ec = ownerOP.getExecutionContext();
    RDBMSStoreManager storeMgr = table.getStoreManager();
    java.util.Map value = (java.util.Map) ownerOP.provideField(getAbsoluteFieldNumber());
    if (containerIsStoredInSingleColumn()) {
        // Do nothing when serialised since we are handled in the main request
        if (value != null) {
            if (mmd.getMap().keyIsPersistent() || mmd.getMap().valueIsPersistent()) {
                // Make sure all persistable keys/values have ObjectProviders
                Set entries = value.entrySet();
                Iterator iter = entries.iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry) iter.next();
                    if (mmd.getMap().keyIsPersistent() && entry.getKey() != null) {
                        Object key = entry.getKey();
                        if (ec.findObjectProvider(key) == null || ec.getApiAdapter().getExecutionContext(key) == null) {
                            ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, key, false, ownerOP, mmd.getAbsoluteFieldNumber());
                        }
                    }
                    if (mmd.getMap().valueIsPersistent() && entry.getValue() != null) {
                        Object val = entry.getValue();
                        if (ec.findObjectProvider(val) == null || ec.getApiAdapter().getExecutionContext(val) == null) {
                            ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, val, false, ownerOP, mmd.getAbsoluteFieldNumber());
                        }
                    }
                }
            }
        }
        return;
    }
    if (value == null) {
        // remove any entries in the map and replace it with an empty SCO wrapper
        ((MapStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null)).clear(ownerOP);
        replaceFieldWithWrapper(ownerOP, null);
        return;
    }
    if (value instanceof BackedSCO) {
        // Already have a SCO value, so flush outstanding updates
        ownerOP.getExecutionContext().flushOperationsForBackingStore(((BackedSCO) value).getBackingStore(), ownerOP);
        return;
    }
    if (mmd.isCascadeUpdate()) {
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007009", mmd.getFullFieldName()));
        }
        // Update the datastore with this value of map (clear old entries and add new ones)
        // This method could be called in two situations
        // 1). Update a map field of an object, so UpdateRequest is called, which calls here
        // 2). Persist a new object, and it needed to wait til the element was inserted so
        // goes into dirty state and then flush() triggers UpdateRequest, which comes here
        MapStore store = ((MapStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, value.getClass()));
        // TODO Consider making this more efficient picking the ones to remove/add
        // e.g use an update() method on the backing store like for CollectionStore
        store.clear(ownerOP);
        store.putAll(ownerOP, value);
        // Replace the field with a wrapper containing these entries
        replaceFieldWithWrapper(ownerOP, value);
    } else {
        // User doesnt want to update by reachability
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007008", mmd.getFullFieldName()));
        }
        return;
    }
}
Also used : Set(java.util.Set) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) ExecutionContext(org.datanucleus.ExecutionContext) Map(java.util.Map) Iterator(java.util.Iterator) MapStore(org.datanucleus.store.types.scostore.MapStore) Map(java.util.Map)

Example 3 with BackedSCO

use of org.datanucleus.store.types.wrappers.backed.BackedSCO in project datanucleus-rdbms by datanucleus.

the class FKListStore method set.

/**
 * Method to set an object in the List at a position.
 * @param ownerOP ObjectProvider for the owner
 * @param index The item index
 * @param element What to set it to.
 * @param allowDependentField Whether to enable dependent-field deletes during the set
 * @return The value before setting.
 */
public E set(ObjectProvider ownerOP, int index, Object element, boolean allowDependentField) {
    // Last argument means don't set the position on any INSERT
    validateElementForWriting(ownerOP, element, -1);
    // Find the original element at this position
    E oldElement = null;
    List fieldVal = (List) ownerOP.provideField(ownerMemberMetaData.getAbsoluteFieldNumber());
    if (fieldVal != null && fieldVal instanceof BackedSCO && ((BackedSCO) fieldVal).isLoaded()) {
        // Already loaded in the wrapper
        oldElement = (E) fieldVal.get(index);
    } else {
        oldElement = get(ownerOP, index);
    }
    ManagedConnection mconn = null;
    try {
        ExecutionContext ec = ownerOP.getExecutionContext();
        SQLController sqlControl = storeMgr.getSQLController();
        mconn = storeMgr.getConnectionManager().getConnection(ec);
        // Unset the existing object from this position
        String theUnsetStmt = getUnsetStmt();
        try {
            PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, theUnsetStmt, false);
            try {
                int jdbcPosition = 1;
                jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerOP, ec, ps, jdbcPosition, this);
                if (orderMapping != null) {
                    jdbcPosition = BackingStoreHelper.populateOrderInStatement(ec, ps, index, jdbcPosition, orderMapping);
                }
                if (relationDiscriminatorMapping != null) {
                    jdbcPosition = BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, this);
                }
                sqlControl.executeStatementUpdate(ec, mconn, theUnsetStmt, ps, true);
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } catch (SQLException e) {
            throw new NucleusDataStoreException(Localiser.msg("056015", theUnsetStmt), e);
        } finally {
        }
        // Set the new object at this position
        String theSetStmt = getSetStmt(element);
        try {
            PreparedStatement ps2 = sqlControl.getStatementForUpdate(mconn, theSetStmt, false);
            try {
                ComponentInfo elemInfo = getComponentInfoForElement(element);
                JavaTypeMapping elemMapping = this.elementMapping;
                JavaTypeMapping orderMapping = this.orderMapping;
                if (elemInfo != null) {
                    elemMapping = elemInfo.getDatastoreClass().getIdMapping();
                    orderMapping = elemInfo.getDatastoreClass().getExternalMapping(ownerMemberMetaData, MappingType.EXTERNAL_INDEX);
                }
                int jdbcPosition = 1;
                jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerOP, ec, ps2, jdbcPosition, this);
                if (orderMapping != null) {
                    jdbcPosition = BackingStoreHelper.populateOrderInStatement(ec, ps2, index, jdbcPosition, orderMapping);
                }
                if (relationDiscriminatorMapping != null) {
                    jdbcPosition = BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps2, jdbcPosition, this);
                }
                jdbcPosition = BackingStoreHelper.populateElementForWhereClauseInStatement(ec, ps2, element, jdbcPosition, elemMapping);
                sqlControl.executeStatementUpdate(ec, mconn, theSetStmt, ps2, true);
            } finally {
                sqlControl.closeStatement(mconn, ps2);
            }
        } catch (SQLException e) {
            throw new NucleusDataStoreException(Localiser.msg("056015", theSetStmt), e);
        }
    } finally {
        if (mconn != null) {
            mconn.release();
        }
    }
    // Dependent field
    boolean dependent = getOwnerMemberMetaData().getCollection().isDependentElement();
    if (getOwnerMemberMetaData().isCascadeRemoveOrphans()) {
        dependent = true;
    }
    if (dependent && allowDependentField) {
        if (oldElement != null) {
            // Delete the element if it is dependent and doesnt have a duplicate entry in the list
            ownerOP.getExecutionContext().deleteObjectInternal(oldElement);
        }
    }
    return oldElement;
}
Also used : SQLException(java.sql.SQLException) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) PreparedStatement(java.sql.PreparedStatement) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO) SQLController(org.datanucleus.store.rdbms.SQLController) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) List(java.util.List) ArrayList(java.util.ArrayList) ManagedConnection(org.datanucleus.store.connection.ManagedConnection)

Example 4 with BackedSCO

use of org.datanucleus.store.types.wrappers.backed.BackedSCO in project datanucleus-rdbms by datanucleus.

the class JoinListStore method set.

/**
 * Method to set an object in the List.
 * @param op ObjectProvider for the owner
 * @param index The item index
 * @param element What to set it to.
 * @param allowDependentField Whether to allow dependent field deletes
 * @return The value before setting.
 */
public E set(ObjectProvider op, int index, Object element, boolean allowDependentField) {
    ExecutionContext ec = op.getExecutionContext();
    validateElementForWriting(ec, element, null);
    // Find the original element at this position
    E oldElement = null;
    List fieldVal = (List) op.provideField(ownerMemberMetaData.getAbsoluteFieldNumber());
    if (fieldVal != null && fieldVal instanceof BackedSCO && ((BackedSCO) fieldVal).isLoaded()) {
        // Already loaded in the wrapper
        oldElement = (E) fieldVal.get(index);
    } else {
        oldElement = get(op, index);
    }
    // Check for dynamic schema updates prior to update
    if (storeMgr.getBooleanObjectProperty(RDBMSPropertyNames.PROPERTY_RDBMS_DYNAMIC_SCHEMA_UPDATES).booleanValue()) {
        DynamicSchemaFieldManager dynamicSchemaFM = new DynamicSchemaFieldManager(storeMgr, op);
        Collection coll = new ArrayList();
        coll.add(element);
        dynamicSchemaFM.storeObjectField(getOwnerMemberMetaData().getAbsoluteFieldNumber(), coll);
        if (dynamicSchemaFM.hasPerformedSchemaUpdates()) {
            setStmt = null;
        }
    }
    String theSetStmt = getSetStmt();
    try {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        SQLController sqlControl = storeMgr.getSQLController();
        try {
            PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, theSetStmt, false);
            try {
                int jdbcPosition = 1;
                jdbcPosition = BackingStoreHelper.populateElementInStatement(ec, ps, element, jdbcPosition, elementMapping);
                jdbcPosition = BackingStoreHelper.populateOwnerInStatement(op, ec, ps, jdbcPosition, this);
                if (getOwnerMemberMetaData().getOrderMetaData() != null && !getOwnerMemberMetaData().getOrderMetaData().isIndexedList()) {
                    // Ordered list, so can't easily do a set!!!
                    NucleusLogger.PERSISTENCE.warn("Calling List.addElement at a position for an ordered list is a stupid thing to do; the ordering is set my the ordering specification. Use an indexed list to do this correctly");
                } else {
                    jdbcPosition = BackingStoreHelper.populateOrderInStatement(ec, ps, index, jdbcPosition, orderMapping);
                }
                if (relationDiscriminatorMapping != null) {
                    jdbcPosition = BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, this);
                }
                sqlControl.executeStatementUpdate(ec, mconn, theSetStmt, ps, true);
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException e) {
        throw new NucleusDataStoreException(Localiser.msg("056015", theSetStmt), e);
    }
    // Dependent field
    CollectionMetaData collmd = ownerMemberMetaData.getCollection();
    boolean dependent = collmd.isDependentElement();
    if (ownerMemberMetaData.isCascadeRemoveOrphans()) {
        dependent = true;
    }
    if (dependent && !collmd.isEmbeddedElement() && allowDependentField) {
        if (oldElement != null && !contains(op, oldElement)) {
            // Delete the element if it is dependent and doesn't have a duplicate entry in the list
            ec.deleteObjectInternal(oldElement);
        }
    }
    return oldElement;
}
Also used : SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) PreparedStatement(java.sql.PreparedStatement) CollectionMetaData(org.datanucleus.metadata.CollectionMetaData) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO) SQLController(org.datanucleus.store.rdbms.SQLController) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) DynamicSchemaFieldManager(org.datanucleus.store.rdbms.fieldmanager.DynamicSchemaFieldManager) Collection(java.util.Collection) List(java.util.List) ArrayList(java.util.ArrayList) ManagedConnection(org.datanucleus.store.connection.ManagedConnection)

Example 5 with BackedSCO

use of org.datanucleus.store.types.wrappers.backed.BackedSCO in project datanucleus-rdbms by datanucleus.

the class CollectionMapping method preDelete.

/**
 * Method to be called before any delete of the owner class element.
 * @param ownerOP ObjectProvider of the owner
 */
public void preDelete(ObjectProvider ownerOP) {
    if (containerIsStoredInSingleColumn()) {
        // Field is stored with the main object so nothing to clean up
        return;
    }
    // makes sure field is loaded
    ownerOP.isLoaded(getAbsoluteFieldNumber());
    Collection value = (Collection) ownerOP.provideField(getAbsoluteFieldNumber());
    if (value == null) {
        return;
    }
    boolean dependent = mmd.getCollection().isDependentElement();
    if (mmd.isCascadeRemoveOrphans()) {
        dependent = true;
    }
    boolean hasJoin = (mmd.getJoinMetaData() != null);
    boolean hasFK = false;
    if (!hasJoin) {
        if (mmd.getElementMetaData() != null && mmd.getElementMetaData().getForeignKeyMetaData() != null) {
            // FK collection, using <element> FK spec
            hasFK = true;
        } else if (mmd.getForeignKeyMetaData() != null) {
            // FK collection, using <field> FK spec
            hasFK = true;
        }
        AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(ownerOP.getExecutionContext().getClassLoaderResolver());
        if (relatedMmds != null && relatedMmds[0].getForeignKeyMetaData() != null) {
            // FK collection (bidir), using <field> FK spec at other end
            hasFK = true;
        }
    }
    if (ownerOP.getExecutionContext().getStringProperty(PropertyNames.PROPERTY_DELETION_POLICY).equals("JDO2")) {
        // JDO doesn't currently take note of foreign-key
        hasFK = false;
    }
    if (ownerOP.getExecutionContext().getManageRelations()) {
        ownerOP.getExecutionContext().getRelationshipManager(ownerOP).relationChange(getAbsoluteFieldNumber(), value, null);
    }
    // TODO Why dont we just do clear here always ? The backing store should take care of if nulling or deleting etc
    if (dependent || hasJoin || !hasFK) {
        // or there are no FKs specified (in which case we need to clean up)
        if (!(value instanceof SCO)) {
            value = (Collection) SCOUtils.wrapSCOField(ownerOP, getAbsoluteFieldNumber(), value, true);
        }
        value.clear();
        // Flush any outstanding updates
        ownerOP.getExecutionContext().flushOperationsForBackingStore(((BackedSCO) value).getBackingStore(), ownerOP);
    }
}
Also used : Collection(java.util.Collection) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) SCO(org.datanucleus.store.types.SCO) BackedSCO(org.datanucleus.store.types.wrappers.backed.BackedSCO)

Aggregations

BackedSCO (org.datanucleus.store.types.wrappers.backed.BackedSCO)8 ExecutionContext (org.datanucleus.ExecutionContext)6 Collection (java.util.Collection)4 SCO (org.datanucleus.store.types.SCO)4 ObjectProvider (org.datanucleus.state.ObjectProvider)3 PreparedStatement (java.sql.PreparedStatement)2 SQLException (java.sql.SQLException)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 Map (java.util.Map)2 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)2 ReachableObjectNotCascadedException (org.datanucleus.exceptions.ReachableObjectNotCascadedException)2 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)2 SQLController (org.datanucleus.store.rdbms.SQLController)2 CollectionStore (org.datanucleus.store.types.scostore.CollectionStore)2 Iterator (java.util.Iterator)1 Set (java.util.Set)1 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)1 CollectionMetaData (org.datanucleus.metadata.CollectionMetaData)1 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)1