Search in sources :

Example 11 with ParameterSetter

use of org.datanucleus.store.rdbms.fieldmanager.ParameterSetter in project datanucleus-rdbms by datanucleus.

the class OracleBlobRDBMSMapping method updateBlobColumn.

/**
 * Convenience method to update the contents of a BLOB column.
 * Oracle requires that a BLOB is initialised with EMPTY_BLOB() and then you retrieve
 * the column and update its BLOB value. Performs a statement
 * <pre>
 * SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE
 * </pre>
 * and then updates the Blob value returned.
 * @param op ObjectProvider of the object
 * @param table Table storing the BLOB column
 * @param mapping Datastore mapping for the BLOB column
 * @param bytes The bytes to store in the BLOB
 * @throws NucleusObjectNotFoundException thrown if an object isnt found
 * @throws NucleusDataStoreException thrown if an error occurs in datastore communication
 */
@SuppressWarnings("deprecation")
public static void updateBlobColumn(ObjectProvider op, Table table, DatastoreMapping mapping, byte[] bytes) {
    ExecutionContext ec = op.getExecutionContext();
    RDBMSStoreManager storeMgr = table.getStoreManager();
    // Don't support join tables yet
    DatastoreClass classTable = (DatastoreClass) table;
    SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
    // 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.getJavaTypeMapping());
    sqlStmt.select(blobSqlTbl, mapping.getColumn(), null);
    StatementClassMapping mappingDefinition = new StatementClassMapping();
    AbstractClassMetaData cmd = op.getClassMetaData();
    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.getNumberOfDatastoreMappings()];
            for (int j = 0; j < pkMapping.getNumberOfDatastoreMappings(); j++) {
                inputParams[j] = inputParamNum++;
            }
            pkIdx.addParameterOccurrence(inputParams);
        }
    }
    String textStmt = sqlStmt.getSQLText().toSQL();
    if (op.isEmbedded()) {
        // This mapping is embedded, so navigate back to the real owner since that is the "id" in the table
        ObjectProvider[] embeddedOwners = ec.getOwnersForEmbeddedObjectProvider(op);
        if (embeddedOwners != null) {
            // Just use the first owner
            // TODO Should check if the owner is stored in this table
            op = embeddedOwners[0];
        }
    }
    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), op.getInternalObjectId());
                    }
                } else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
                    op.provideFields(cmd.getPKMemberPositions(), new ParameterSetter(op, ps, mappingDefinition));
                }
                ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, textStmt, ps);
                try {
                    if (!rs.next()) {
                        throw new NucleusObjectNotFoundException("No such database row", op.getInternalObjectId());
                    }
                    DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
                    int jdbcMajorVersion = dba.getDriverMajorVersion();
                    if (dba.getDatastoreDriverName().equalsIgnoreCase(OracleAdapter.OJDBC_DRIVER_NAME) && jdbcMajorVersion < 10) {
                        // Oracle JDBC drivers version 9 and below use some sh*tty Oracle-specific BLOB type
                        // we have to cast to that, face west, pray whilst saying ommmmmmmmmmm
                        oracle.sql.BLOB blob = null;
                        if (jdbcMajorVersion <= 8) {
                            OracleResultSet ors = (OracleResultSet) rs;
                            blob = ors.getBLOB(1);
                        } else {
                            blob = (oracle.sql.BLOB) rs.getBlob(1);
                        }
                        if (blob != null) {
                            // Deprecated but what can you do
                            blob.putBytes(1, bytes);
                        }
                    } else {
                        // Oracle JDBC drivers 10 and above 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);
    }
}
Also used : SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) OracleResultSet(oracle.jdbc.driver.OracleResultSet) 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) ResultSet(java.sql.ResultSet) OracleResultSet(oracle.jdbc.driver.OracleResultSet) ManagedConnection(org.datanucleus.store.connection.ManagedConnection) PreparedStatement(java.sql.PreparedStatement) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) StatementClassMapping(org.datanucleus.store.rdbms.query.StatementClassMapping) ExecutionContext(org.datanucleus.ExecutionContext) ObjectProvider(org.datanucleus.state.ObjectProvider) DatastoreAdapter(org.datanucleus.store.rdbms.adapter.DatastoreAdapter) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) Blob(java.sql.Blob) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

ParameterSetter (org.datanucleus.store.rdbms.fieldmanager.ParameterSetter)11 StatementMappingIndex (org.datanucleus.store.rdbms.query.StatementMappingIndex)11 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)9 StatementClassMapping (org.datanucleus.store.rdbms.query.StatementClassMapping)9 PreparedStatement (java.sql.PreparedStatement)8 SQLException (java.sql.SQLException)8 ExecutionContext (org.datanucleus.ExecutionContext)8 NucleusDataStoreException (org.datanucleus.exceptions.NucleusDataStoreException)8 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)8 ManagedConnection (org.datanucleus.store.connection.ManagedConnection)8 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)8 SQLController (org.datanucleus.store.rdbms.SQLController)8 ArrayList (java.util.ArrayList)6 List (java.util.List)6 ObjectProvider (org.datanucleus.state.ObjectProvider)6 ResultSet (java.sql.ResultSet)5 NucleusObjectNotFoundException (org.datanucleus.exceptions.NucleusObjectNotFoundException)5 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)5 LockMode (org.datanucleus.state.LockMode)3 Timestamp (java.sql.Timestamp)2