Search in sources :

Example 91 with ExecutionContext

use of org.datanucleus.ExecutionContext in project datanucleus-rdbms by datanucleus.

the class RDBMSPersistenceHandler method fetchObject.

// ------------------------------ Fetch ----------------------------------
/**
 * Fetches (fields of) a persistent object from the database.
 * This does a single SELECT on the candidate of the class in question. Will join to inherited
 * tables as appropriate to get values persisted into other tables. Can also join to the tables of
 * related objects (1-1, N-1) as neccessary to retrieve those objects.
 * @param op Object Provider of the object to be fetched.
 * @param memberNumbers The numbers of the members to be fetched.
 * @throws NucleusObjectNotFoundException if the object doesn't exist
 * @throws NucleusDataStoreException when an error occurs in the datastore communication
 */
public void fetchObject(ObjectProvider op, int[] memberNumbers) {
    ExecutionContext ec = op.getExecutionContext();
    ClassLoaderResolver clr = ec.getClassLoaderResolver();
    // Extract metadata of members to process
    AbstractMemberMetaData[] mmds = null;
    if (memberNumbers != null && memberNumbers.length > 0) {
        int[] memberNumbersToProcess = memberNumbers;
        AbstractClassMetaData cmd = op.getClassMetaData();
        if (storeMgr.getBooleanProperty(RDBMSPropertyNames.PROPERTY_RDBMS_FETCH_UNLOADED_AUTO)) {
            // Here we simply load up any unloaded non-relation or 1-1/N-1 members
            if (!op.getLifecycleState().isDeleted()) {
                // Check if this will actually do a SELECT (because we don't want to impose that if not otherwise)
                boolean fetchPerformsSelect = false;
                for (int i = 0; i < memberNumbers.length; i++) {
                    AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(memberNumbers[i]);
                    RelationType relationType = mmd.getRelationType(clr);
                    if (relationType != RelationType.ONE_TO_MANY_UNI && relationType != RelationType.ONE_TO_MANY_BI && relationType != RelationType.MANY_TO_MANY_BI) {
                        fetchPerformsSelect = true;
                        break;
                    }
                }
                if (fetchPerformsSelect) {
                    // Definitely does a SELECT, so try to identify any additional non-relation or 1-1, N-1
                    // members that aren't loaded that could be fetched right now in this call.
                    List<Integer> memberNumberList = new ArrayList<>();
                    for (int i = 0; i < memberNumbers.length; i++) {
                        memberNumberList.add(memberNumbers[i]);
                    }
                    // Check if we could retrieve any other unloaded fields in this call
                    boolean[] loadedFlags = op.getLoadedFields();
                    for (int i = 0; i < loadedFlags.length; i++) {
                        boolean requested = false;
                        for (int j = 0; j < memberNumbers.length; j++) {
                            if (memberNumbers[j] == i) {
                                requested = true;
                                break;
                            }
                        }
                        if (!requested && !loadedFlags[i]) {
                            AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(i);
                            RelationType relType = mmd.getRelationType(clr);
                            if (relType == RelationType.NONE || relType == RelationType.ONE_TO_ONE_BI || relType == RelationType.ONE_TO_ONE_UNI) {
                                memberNumberList.add(i);
                            }
                        }
                    }
                    memberNumbersToProcess = new int[memberNumberList.size()];
                    int i = 0;
                    Iterator<Integer> fieldNumberIter = memberNumberList.iterator();
                    while (fieldNumberIter.hasNext()) {
                        memberNumbersToProcess[i++] = fieldNumberIter.next();
                    }
                }
            }
        }
        // Convert the field numbers for this class into their metadata for the class
        mmds = new AbstractMemberMetaData[memberNumbersToProcess.length];
        for (int i = 0; i < mmds.length; i++) {
            mmds[i] = cmd.getMetaDataForManagedMemberAtAbsolutePosition(memberNumbersToProcess[i]);
        }
    }
    if (op.isEmbedded()) {
        StringBuilder str = new StringBuilder();
        if (mmds != null) {
            for (int i = 0; i < mmds.length; i++) {
                if (i > 0) {
                    str.append(',');
                }
                str.append(mmds[i].getName());
            }
        }
        NucleusLogger.PERSISTENCE.info("Request to load fields \"" + str.toString() + "\" of class " + op.getClassMetaData().getFullClassName() + " but object is embedded, so ignored");
    } else {
        if (ec.getStatistics() != null) {
            ec.getStatistics().incrementFetchCount();
        }
        DatastoreClass table = getDatastoreClass(op.getClassMetaData().getFullClassName(), clr);
        Request req = getFetchRequest(table, mmds, op.getClassMetaData(), clr);
        req.execute(op);
    }
}
Also used : ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) ArrayList(java.util.ArrayList) LocateRequest(org.datanucleus.store.rdbms.request.LocateRequest) Request(org.datanucleus.store.rdbms.request.Request) FetchRequest(org.datanucleus.store.rdbms.request.FetchRequest) DeleteRequest(org.datanucleus.store.rdbms.request.DeleteRequest) InsertRequest(org.datanucleus.store.rdbms.request.InsertRequest) LocateBulkRequest(org.datanucleus.store.rdbms.request.LocateBulkRequest) UpdateRequest(org.datanucleus.store.rdbms.request.UpdateRequest) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ExecutionContext(org.datanucleus.ExecutionContext) RelationType(org.datanucleus.metadata.RelationType) SecondaryDatastoreClass(org.datanucleus.store.rdbms.table.SecondaryDatastoreClass) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 92 with ExecutionContext

use of org.datanucleus.ExecutionContext in project datanucleus-rdbms by datanucleus.

the class ScrollableQueryResult method getObjectForIndex.

/**
 * Accessor for the result object at an index.
 * If the object has already been processed will return that object,
 * otherwise will retrieve the object using the factory.
 * @param index The list index position
 * @return The result object
 */
protected E getObjectForIndex(int index) {
    if (resultsObjsByIndex != null) {
        // Caching objects, so check the cache for this index
        E obj = resultsObjsByIndex.get(index);
        if (obj != null) {
            // Already retrieved so return it
            return obj;
        }
    }
    if (rs == null) {
        throw new NucleusUserException("Results for query have already been closed. Perhaps you called flush(), closed the query, or ended a transaction");
    }
    try {
        // ResultSet is numbered 1, 2, ... N
        // List is indexed 0, 1, 2, ... N-1
        rs.absolute(index + 1);
        E obj = rof.getObject();
        JDBCUtils.logWarnings(rs);
        // Process any bulk loaded members
        if (bulkLoadedValueByMemberNumber != null) {
            ExecutionContext ec = query.getExecutionContext();
            Map<Integer, Object> memberValues = bulkLoadedValueByMemberNumber.get(api.getIdForObject(obj));
            if (memberValues != null) {
                ObjectProvider op = ec.findObjectProvider(obj);
                Iterator<Map.Entry<Integer, Object>> memberValIter = memberValues.entrySet().iterator();
                while (memberValIter.hasNext()) {
                    Map.Entry<Integer, Object> memberValueEntry = memberValIter.next();
                    op.replaceField(memberValueEntry.getKey(), memberValueEntry.getValue());
                }
                op.replaceAllLoadedSCOFieldsWithWrappers();
            }
        }
        if (resultsObjsByIndex != null) {
            // Put it in our cache, keyed by the list index
            resultsObjsByIndex.put(index, obj);
            if (resultIdsByPosition != null) {
                resultIdsByPosition.put(index, api.getIdForObject(obj));
            }
        }
        return obj;
    } catch (SQLException sqe) {
        throw api.getDataStoreExceptionForException(Localiser.msg("052601", sqe.getMessage()), sqe);
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) SQLException(java.sql.SQLException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ObjectProvider(org.datanucleus.state.ObjectProvider) HashMap(java.util.HashMap) ConcurrentReferenceHashMap(org.datanucleus.util.ConcurrentReferenceHashMap) Map(java.util.Map)

Example 93 with ExecutionContext

use of org.datanucleus.ExecutionContext in project datanucleus-rdbms by datanucleus.

the class FKArrayStore method updateElementFk.

/**
 * Update a FK and element position in the element.
 * @param ownerOP ObjectProvider for the owner
 * @param element The element to update
 * @param owner The owner object to set in the FK
 * @param index The index position (or -1 if not known)
 * @return Whether it was performed successfully
 */
private boolean updateElementFk(ObjectProvider ownerOP, E element, Object owner, int index) {
    if (element == null) {
        return false;
    }
    boolean retval;
    String updateFkStmt = getUpdateFkStmt();
    ExecutionContext ec = ownerOP.getExecutionContext();
    try {
        ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
        SQLController sqlControl = storeMgr.getSQLController();
        try {
            PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, updateFkStmt, false);
            try {
                int jdbcPosition = 1;
                if (elementInfo.length > 1) {
                    DatastoreClass table = storeMgr.getDatastoreClass(element.getClass().getName(), clr);
                    if (table != null) {
                        ps.setString(jdbcPosition++, table.toString());
                    } else {
                        NucleusLogger.PERSISTENCE.info(">> FKArrayStore.updateElementFK : need to set table in statement but dont know table where to store " + element);
                    }
                }
                if (owner == null) {
                    ownerMapping.setObject(ec, ps, MappingHelper.getMappingIndices(jdbcPosition, ownerMapping), null);
                    jdbcPosition += ownerMapping.getNumberOfDatastoreMappings();
                } else {
                    jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerOP, ec, ps, jdbcPosition, this);
                }
                jdbcPosition = BackingStoreHelper.populateOrderInStatement(ec, ps, index, jdbcPosition, orderMapping);
                if (relationDiscriminatorMapping != null) {
                    jdbcPosition = BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, this);
                }
                jdbcPosition = BackingStoreHelper.populateElementInStatement(ec, ps, element, jdbcPosition, elementMapping);
                sqlControl.executeStatementUpdate(ec, mconn, updateFkStmt, ps, true);
                retval = true;
            } finally {
                sqlControl.closeStatement(mconn, ps);
            }
        } finally {
            mconn.release();
        }
    } catch (SQLException e) {
        throw new NucleusDataStoreException(Localiser.msg("056027", updateFkStmt), e);
    }
    return retval;
}
Also used : NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) SQLException(java.sql.SQLException) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) PreparedStatement(java.sql.PreparedStatement) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) SQLController(org.datanucleus.store.rdbms.SQLController)

Example 94 with ExecutionContext

use of org.datanucleus.ExecutionContext in project datanucleus-rdbms by datanucleus.

the class FKListStore method clear.

/**
 * Method to clear the List.
 * This is called by the List.clear() method, or when the container object is being deleted
 * and the elements are to be removed (maybe for dependent field), or also when updating a Collection
 * and removing all existing prior to adding all new.
 * @param ownerOP ObjectProvider for the owner
 */
public void clear(ObjectProvider ownerOP) {
    boolean deleteElements = false;
    ExecutionContext ec = ownerOP.getExecutionContext();
    boolean dependent = ownerMemberMetaData.getCollection().isDependentElement();
    if (ownerMemberMetaData.isCascadeRemoveOrphans()) {
        dependent = true;
    }
    if (dependent) {
        // Elements are dependent and can't exist on their own, so delete them all
        NucleusLogger.DATASTORE.debug(Localiser.msg("056034"));
        deleteElements = true;
    } else {
        if (ownerMapping.isNullable() && orderMapping == null) {
            // Field is not dependent, and nullable so we null the FK
            NucleusLogger.DATASTORE.debug(Localiser.msg("056036"));
            deleteElements = false;
        } else if (ownerMapping.isNullable() && orderMapping != null && orderMapping.isNullable()) {
            // Field is not dependent, and nullable so we null the FK
            NucleusLogger.DATASTORE.debug(Localiser.msg("056036"));
            deleteElements = false;
        } else {
            // Field is not dependent, and not nullable so we just delete the elements
            NucleusLogger.DATASTORE.debug(Localiser.msg("056035"));
            deleteElements = true;
        }
    }
    if (deleteElements) {
        // Find elements present in the datastore and delete them one-by-one
        Iterator elementsIter = iterator(ownerOP);
        if (elementsIter != null) {
            while (elementsIter.hasNext()) {
                Object element = elementsIter.next();
                if (ec.getApiAdapter().isPersistable(element) && ec.getApiAdapter().isDeleted(element)) {
                    // Element is waiting to be deleted so flush it (it has the FK)
                    ObjectProvider objSM = ec.findObjectProvider(element);
                    objSM.flush();
                } else {
                    // Element not yet marked for deletion so go through the normal process
                    ec.deleteObjectInternal(element);
                }
            }
        }
    } else {
        boolean ownerSoftDelete = ownerOP.getClassMetaData().hasExtension(MetaData.EXTENSION_CLASS_SOFTDELETE);
        if (!ownerSoftDelete) {
            // Clear without delete
            // TODO If the relation is bidirectional we need to clear the owner in the element
            String clearNullifyStmt = getClearNullifyStmt();
            try {
                ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
                SQLController sqlControl = storeMgr.getSQLController();
                try {
                    PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, clearNullifyStmt, false);
                    try {
                        int jdbcPosition = 1;
                        jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerOP, ec, ps, jdbcPosition, this);
                        if (relationDiscriminatorMapping != null) {
                            BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, this);
                        }
                        sqlControl.executeStatementUpdate(ec, mconn, clearNullifyStmt, ps, true);
                    } finally {
                        sqlControl.closeStatement(mconn, ps);
                    }
                } finally {
                    mconn.release();
                }
            } catch (SQLException e) {
                throw new NucleusDataStoreException(Localiser.msg("056013", clearNullifyStmt), e);
            }
        }
    }
}
Also used : NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) ExecutionContext(org.datanucleus.ExecutionContext) SQLException(java.sql.SQLException) ListIterator(java.util.ListIterator) Iterator(java.util.Iterator) ObjectProvider(org.datanucleus.state.ObjectProvider) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) PreparedStatement(java.sql.PreparedStatement) SQLController(org.datanucleus.store.rdbms.SQLController)

Example 95 with ExecutionContext

use of org.datanucleus.ExecutionContext in project datanucleus-rdbms by datanucleus.

the class FKListStore method internalRemove.

/**
 * Convenience method to remove the specified element from the List.
 * @param ownerOP ObjectProvider for the owner
 * @param element The element
 * @return Whether the List was modified
 */
protected boolean internalRemove(ObjectProvider ownerOP, Object element, int size) {
    if (indexedList) {
        // Indexed List
        // The element can be at one position only (no duplicates allowed in FK list)
        int index = indexOf(ownerOP, element);
        if (index == -1) {
            return false;
        }
        internalRemoveAt(ownerOP, index, size);
    } else {
        // Ordered List - no index so null the FK (if nullable) or delete the element
        if (ownerMapping.isNullable()) {
            // Nullify the FK
            ExecutionContext ec = ownerOP.getExecutionContext();
            ObjectProvider elementSM = ec.findObjectProvider(element);
            if (relationType == RelationType.ONE_TO_MANY_BI) {
                // Set field in element to null (so it nulls the FK)
                // TODO This is ManagedRelations - move into RelationshipManager
                elementSM.replaceFieldMakeDirty(ownerMemberMetaData.getRelatedMemberMetaData(clr)[0].getAbsoluteFieldNumber(), null);
                if (ownerOP.getExecutionContext().isFlushing()) {
                    elementSM.flush();
                }
            } else {
                // Null the (external) FK in the element
                updateElementFk(ownerOP, element, null, -1);
            }
        } else {
            // Delete the element
            ownerOP.getExecutionContext().deleteObjectInternal(element);
        }
    }
    return true;
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) ObjectProvider(org.datanucleus.state.ObjectProvider)

Aggregations

ExecutionContext (org.datanucleus.ExecutionContext)178 ObjectProvider (org.datanucleus.state.ObjectProvider)85 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)73 SQLException (java.sql.SQLException)66 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)64 SQLController (org.datanucleus.store.rdbms.SQLController)63 PreparedStatement (java.sql.PreparedStatement)62 Iterator (java.util.Iterator)56 MappedDatastoreException (org.datanucleus.store.rdbms.exceptions.MappedDatastoreException)27 ResultSet (java.sql.ResultSet)26 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)26 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)25 Map (java.util.Map)23 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)20 Collection (java.util.Collection)18 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)18 StatementClassMapping (org.datanucleus.store.rdbms.query.StatementClassMapping)17 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)16 SCOCollectionIterator (org.datanucleus.store.types.SCOCollectionIterator)16 ArrayList (java.util.ArrayList)15