Search in sources :

Example 21 with DNStateManager

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

the class OracleArrayMapping method postUpdate.

/**
 * Method to be called after any update of the owner class element.
 * @param ownerSM StateManager of the owner
 */
public void postUpdate(DNStateManager ownerSM) {
    if (containerIsStoredInSingleColumn()) {
        Object value = ownerSM.provideField(mmd.getAbsoluteFieldNumber());
        if (value == null) {
            return;
        }
        ExecutionContext ec = ownerSM.getExecutionContext();
        if (mmd.getArray().elementIsPersistent()) {
            // Make sure all persistable elements have StateManagers
            Object[] arrElements = (Object[]) value;
            for (Object elem : arrElements) {
                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_ARRAY_ELEMENT_PC);
                    }
                }
            }
        }
    } else {
        super.postUpdate(ownerSM);
    }
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) DNStateManager(org.datanucleus.state.DNStateManager)

Example 22 with DNStateManager

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

the class SerialisedReferenceMapping method getObject.

/**
 * Method to extract the value of the persistable from a ResultSet.
 * @param ec execution context
 * @param exprIndex The parameter positions in the result set to use.
 * @param ownerSM StateManager for the owning object
 * @param resultSet The ResultSet
 * @param fieldNumber Absolute number of field in owner object
 * @return The (deserialised) persistable object
 */
@Override
public Object getObject(ExecutionContext ec, ResultSet resultSet, int[] exprIndex, DNStateManager ownerSM, int fieldNumber) {
    Object obj = getColumnMapping(0).getObject(resultSet, exprIndex[0]);
    ApiAdapter api = ec.getApiAdapter();
    if (api.isPersistable(obj)) {
        // Assign a StateManager to the serialised object if none present
        DNStateManager embSM = ec.findStateManager(obj);
        if (embSM == null || api.getExecutionContext(obj) == null) {
            ec.getNucleusContext().getStateManagerFactory().newForEmbedded(ec, obj, false, ownerSM, fieldNumber, PersistableObjectType.EMBEDDED_PC);
        }
    }
    return obj;
}
Also used : ApiAdapter(org.datanucleus.api.ApiAdapter) DNStateManager(org.datanucleus.state.DNStateManager)

Example 23 with DNStateManager

use of org.datanucleus.state.DNStateManager 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 24 with DNStateManager

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

the class OracleBlobColumnMapping method setPostProcessing.

@SuppressWarnings("deprecation")
@Override
public void setPostProcessing(DNStateManager sm, Object value) {
    // Oracle requires that a BLOB is initialised with EMPTY_BLOB() and then you retrieve the column and update its BLOB value. Performs a statement
    // SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE
    // and then updates the Blob value returned.
    ExecutionContext ec = sm.getExecutionContext();
    byte[] bytes = (byte[]) value;
    Table table = column.getTable();
    RDBMSStoreManager storeMgr = table.getStoreManager();
    if (table instanceof DatastoreClass) {
        // BLOB within a primary table
        DatastoreClass classTable = (DatastoreClass) table;
        // Generate "SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE" statement
        SelectStatement sqlStmt = new SelectStatement(storeMgr, table, null, null);
        sqlStmt.setClassLoaderResolver(ec.getClassLoaderResolver());
        sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
        SQLTable blobSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), mapping);
        sqlStmt.select(blobSqlTbl, column, null);
        StatementClassMapping mappingDefinition = new StatementClassMapping();
        AbstractClassMetaData cmd = sm.getClassMetaData();
        SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
        int inputParamNum = 1;
        if (cmd.getIdentityType() == IdentityType.DATASTORE) {
            // Datastore identity value for input
            JavaTypeMapping datastoreIdMapping = classTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
            SQLExpression expr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), datastoreIdMapping);
            SQLExpression val = exprFactory.newLiteralParameter(sqlStmt, datastoreIdMapping, null, "ID");
            sqlStmt.whereAnd(expr.eq(val), true);
            StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
            if (datastoreIdx == null) {
                datastoreIdx = new StatementMappingIndex(datastoreIdMapping);
                mappingDefinition.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdx);
            }
            datastoreIdx.addParameterOccurrence(new int[] { inputParamNum });
        } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
            // Application identity value(s) for input
            int[] pkNums = cmd.getPKMemberPositions();
            for (int i = 0; i < pkNums.length; i++) {
                AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[i]);
                JavaTypeMapping pkMapping = classTable.getMemberMapping(mmd);
                SQLExpression expr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), pkMapping);
                SQLExpression val = exprFactory.newLiteralParameter(sqlStmt, pkMapping, null, "PK" + i);
                sqlStmt.whereAnd(expr.eq(val), true);
                StatementMappingIndex pkIdx = mappingDefinition.getMappingForMemberPosition(pkNums[i]);
                if (pkIdx == null) {
                    pkIdx = new StatementMappingIndex(pkMapping);
                    mappingDefinition.addMappingForMember(pkNums[i], pkIdx);
                }
                int[] inputParams = new int[pkMapping.getNumberOfColumnMappings()];
                for (int j = 0; j < pkMapping.getNumberOfColumnMappings(); j++) {
                    inputParams[j] = inputParamNum++;
                }
                pkIdx.addParameterOccurrence(inputParams);
            }
        }
        String textStmt = sqlStmt.getSQLText().toSQL();
        if (sm.isEmbedded()) {
            // This mapping is embedded, so navigate back to the real owner since that is the "id" in the table
            DNStateManager embeddedOwner = ec.getOwnerForEmbeddedStateManager(sm);
            if (embeddedOwner != null) {
                // TODO Should check if the owner is stored in this table
                sm = embeddedOwner;
            }
        }
        try {
            ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
            SQLController sqlControl = storeMgr.getSQLController();
            try {
                PreparedStatement ps = sqlControl.getStatementForQuery(mconn, textStmt);
                try {
                    // Provide the primary key field(s) to the JDBC statement
                    if (cmd.getIdentityType() == IdentityType.DATASTORE) {
                        StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
                        for (int i = 0; i < datastoreIdx.getNumberOfParameterOccurrences(); i++) {
                            classTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, datastoreIdx.getParameterPositionsForOccurrence(i), sm.getInternalObjectId());
                        }
                    } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
                        sm.provideFields(cmd.getPKMemberPositions(), new ParameterSetter(sm, ps, mappingDefinition));
                    }
                    ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, textStmt, ps);
                    try {
                        if (!rs.next()) {
                            throw new NucleusObjectNotFoundException(Localiser.msg("050018", IdentityUtils.getPersistableIdentityForId(sm.getInternalObjectId())));
                        }
                        DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
                        int jdbcMajorVersion = dba.getDriverMajorVersion();
                        if (dba.getDatastoreDriverName().equalsIgnoreCase(OracleAdapter.OJDBC_DRIVER_NAME) && jdbcMajorVersion < 10) {
                            oracle.sql.BLOB blob = null;
                            if (jdbcMajorVersion <= 8) {
                                // Oracle JDBC <= v8
                                // We are effectively doing the following line but don't want to impose having Oracle <= v10 in the CLASSPATH, just any Oracle driver
                                // blob = ((oracle.jdbc.driver.OracleResultSet)rs).getBLOB(1);
                                Method getBlobMethod = ClassUtils.getMethodForClass(rs.getClass(), "getBLOB", new Class[] { int.class });
                                try {
                                    blob = (BLOB) getBlobMethod.invoke(rs, new Object[] { 1 });
                                } catch (Throwable thr) {
                                    throw new NucleusDataStoreException("Error in getting BLOB", thr);
                                }
                            } else {
                                // Oracle JDBC v9
                                blob = (BLOB) rs.getBlob(1);
                            }
                            if (blob != null) {
                                // Deprecated but what can you do
                                blob.putBytes(1, bytes);
                            }
                        } else {
                            // Oracle JDBC v10+ supposedly use the JDBC standard class for Blobs
                            java.sql.Blob blob = rs.getBlob(1);
                            if (blob != null) {
                                blob.setBytes(1, bytes);
                            }
                        }
                    } finally {
                        rs.close();
                    }
                } finally {
                    sqlControl.closeStatement(mconn, ps);
                }
            } finally {
                mconn.release();
            }
        } catch (SQLException e) {
            throw new NucleusDataStoreException("Update of BLOB value failed: " + textStmt, e);
        }
    } else {
        // TODO Support join table
        throw new NucleusDataStoreException("We do not support INSERT/UPDATE BLOB post processing of non-primary table " + table);
    }
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) SQLException(java.sql.SQLException) StatementMappingIndex(org.datanucleus.store.rdbms.query.StatementMappingIndex) ParameterSetter(org.datanucleus.store.rdbms.fieldmanager.ParameterSetter) NucleusObjectNotFoundException(org.datanucleus.exceptions.NucleusObjectNotFoundException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) SQLController(org.datanucleus.store.rdbms.SQLController) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) NucleusDataStoreException(org.datanucleus.exceptions.NucleusDataStoreException) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) BLOB(oracle.sql.BLOB) ResultSet(java.sql.ResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) Table(org.datanucleus.store.rdbms.table.Table) PreparedStatement(java.sql.PreparedStatement) Method(java.lang.reflect.Method) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) ExecutionContext(org.datanucleus.ExecutionContext) DatastoreAdapter(org.datanucleus.store.rdbms.adapter.DatastoreAdapter) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) DNStateManager(org.datanucleus.state.DNStateManager) Blob(java.sql.Blob) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 25 with DNStateManager

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

the class ArrayMapping 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 an array field of an object by replacing the array with a new array,
 * 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 ownerSM StateManager of the owner
 */
public void postUpdate(DNStateManager ownerSM) {
    ExecutionContext ec = ownerSM.getExecutionContext();
    Object value = ownerSM.provideField(getAbsoluteFieldNumber());
    if (containerIsStoredInSingleColumn()) {
        if (value != null) {
            if (mmd.getArray().elementIsPersistent()) {
                // Make sure all persistable elements have StateManagers
                Object[] arrElements = (Object[]) value;
                for (Object elem : arrElements) {
                    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_ARRAY_ELEMENT_PC);
                        }
                    }
                }
            }
        }
        return;
    }
    if (value == null) {
        // array is now null so remove any elements in the array
        ((ArrayStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null)).clear(ownerSM);
        return;
    }
    if (!mmd.isCascadePersist()) {
        // User doesn't want to update by reachability
        if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
            NucleusLogger.PERSISTENCE.debug(Localiser.msg("007008", IdentityUtils.getPersistableIdentityForId(ownerSM.getInternalObjectId()), mmd.getFullFieldName()));
        }
        return;
    }
    if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
        NucleusLogger.PERSISTENCE.debug(Localiser.msg("007009", IdentityUtils.getPersistableIdentityForId(ownerSM.getInternalObjectId()), mmd.getFullFieldName()));
    }
    // Update the datastore
    // TODO Do this more efficiently, removing elements no longer present, and adding new ones
    ArrayStore backingStore = (ArrayStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null);
    backingStore.clear(ownerSM);
    backingStore.set(ownerSM, value);
}
Also used : ExecutionContext(org.datanucleus.ExecutionContext) DNStateManager(org.datanucleus.state.DNStateManager) ArrayStore(org.datanucleus.store.types.scostore.ArrayStore)

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