All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.datanucleus.store.rdbms.mapping.oracle.OracleBlobRDBMSMapping Maven / Gradle / Ivy

/**********************************************************************
Copyright (c) 2005 Brendan De Beer and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
2007 Thomas Marti - added handling for String->BLOB mapping
2009 Andy Jefferson - rewrite SQL to use SQLStatement API methods
    ...
**********************************************************************/
package org.datanucleus.store.rdbms.mapping.oracle;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.StreamCorruptedException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import oracle.jdbc.driver.OracleResultSet;

import org.datanucleus.ClassNameConstants;
import org.datanucleus.ExecutionContext;
import org.datanucleus.exceptions.NucleusDataStoreException;
import org.datanucleus.exceptions.NucleusObjectNotFoundException;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.metadata.IdentityType;
import org.datanucleus.state.ObjectProvider;
import org.datanucleus.store.connection.ManagedConnection;
import org.datanucleus.store.rdbms.mapping.StatementClassMapping;
import org.datanucleus.store.rdbms.mapping.StatementMappingIndex;
import org.datanucleus.store.rdbms.mapping.datastore.BlobImpl;
import org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping;
import org.datanucleus.store.rdbms.mapping.datastore.AbstractDatastoreMapping;
import org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping;
import org.datanucleus.store.rdbms.RDBMSStoreManager;
import org.datanucleus.store.rdbms.SQLController;
import org.datanucleus.store.rdbms.adapter.DatastoreAdapter;
import org.datanucleus.store.rdbms.adapter.OracleAdapter;
import org.datanucleus.store.rdbms.schema.SQLTypeInfo;
import org.datanucleus.store.rdbms.sql.SQLStatement;
import org.datanucleus.store.rdbms.sql.SQLStatementHelper;
import org.datanucleus.store.rdbms.sql.SQLTable;
import org.datanucleus.store.rdbms.sql.expression.SQLExpression;
import org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory;
import org.datanucleus.store.rdbms.table.Column;
import org.datanucleus.store.rdbms.table.DatastoreClass;
import org.datanucleus.store.rdbms.table.Table;
import org.datanucleus.util.NucleusLogger;
import org.datanucleus.util.TypeConversionHelper;

/**
 * Maps a Field to an Oracle BLOB.
 */
public class OracleBlobRDBMSMapping extends AbstractDatastoreMapping
{
    /**
     * Constructor.
     * @param mapping The Java mapping
     * @param storeMgr Store Manager in use
     * @param col Column
     */
    public OracleBlobRDBMSMapping(JavaTypeMapping mapping, RDBMSStoreManager storeMgr, Column col)
    {
        super(storeMgr, mapping);
        column = col;
        initialize();
    }

    /**
     * Creates a OracleBlobRDBMSMapping
     * @param storeMgr Store Manager
     * @param mapping The Java mapping
     */
    protected OracleBlobRDBMSMapping(RDBMSStoreManager storeMgr, JavaTypeMapping mapping)
    {
        super(storeMgr, mapping);
    }

    /**
     * Initialize the mapping.
     */
    private void initialize()
    {
        initTypeInfo();
    }

    /**
     * @see org.datanucleus.store.rdbms.mapping.datastore.AbstractDatastoreMapping#getInsertionInputParameter()
     */
    public String getInsertionInputParameter()
    {
        return "EMPTY_BLOB()";
    }

    /**
     * Accessor for whether this mapping requires values inserting on an INSERT.
     * @return Whether values are to be inserted into this mapping on an INSERT
     */
    public boolean insertValuesOnInsert()
    {
        // We will just insert "EMPTY_BLOB()" above so don't put value in
        return false;
    }

    /**
     * Returns the object to be loaded from the Orale BLOB.
     * @param rs the ResultSet from the query
     * @param param the index in the query
     * @return the object loaded as a byte[]
     * @throws NucleusDataStoreException
     */
    public Object getObject(ResultSet rs, int param)
    {
        Object obj = null;

        try
        {
            Blob blob = rs.getBlob(param);
            if (!rs.wasNull())
            {
                byte[] bytes = blob.getBytes(1,(int)blob.length());
                if (bytes.length < 1)
                {
                    return null;
                }
                try
                {
                    if (getJavaTypeMapping().isSerialised())
                    {
                        BlobImpl b = new BlobImpl(bytes);
                        obj = b.getObject();
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.BOOLEAN_ARRAY))
                    {
                        obj = TypeConversionHelper.getBooleanArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.BYTE_ARRAY))
                    {
                        obj = bytes;
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.CHAR_ARRAY))
                    {
                        obj = TypeConversionHelper.getCharArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_STRING))
                    {
                        obj = new String(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.DOUBLE_ARRAY))
                    {
                        obj = TypeConversionHelper.getDoubleArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.FLOAT_ARRAY))
                    {
                        obj = TypeConversionHelper.getFloatArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.INT_ARRAY))
                    {
                        obj = TypeConversionHelper.getIntArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.LONG_ARRAY))
                    {
                        obj = TypeConversionHelper.getLongArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.SHORT_ARRAY))
                    {
                        obj = TypeConversionHelper.getShortArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_BOOLEAN_ARRAY))
                    {
                        obj = TypeConversionHelper.getBooleanObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_BYTE_ARRAY))
                    {
                        obj = TypeConversionHelper.getByteObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_CHARACTER_ARRAY))
                    {
                        obj = TypeConversionHelper.getCharObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_DOUBLE_ARRAY))
                    {
                        obj = TypeConversionHelper.getDoubleObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_FLOAT_ARRAY))
                    {
                        obj = TypeConversionHelper.getFloatObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_INTEGER_ARRAY))
                    {
                        obj = TypeConversionHelper.getIntObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_LONG_ARRAY))
                    {
                        obj = TypeConversionHelper.getLongObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_SHORT_ARRAY))
                    {
                        obj = TypeConversionHelper.getShortObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(BigDecimal[].class.getName()))
                    {
                        return TypeConversionHelper.getBigDecimalArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(BigInteger[].class.getName()))
                    {
                        return TypeConversionHelper.getBigIntegerArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(java.util.BitSet.class.getName()))
                    {
                        return TypeConversionHelper.getBitSetFromBooleanArray((boolean[]) TypeConversionHelper.getBooleanArrayFromByteArray(bytes));
                    }
                    else
                    {
                        obj = new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject();
                    }
                }
                catch (StreamCorruptedException e)
                {
                    String msg = "StreamCorruptedException: object is corrupted";
                    NucleusLogger.DATASTORE.error(msg);
                    throw new NucleusUserException(msg, e).setFatal();
                }
                catch (IOException e)
                {
                    String msg = "IOException: error when reading object";
                    NucleusLogger.DATASTORE.error(msg);
                    throw new NucleusUserException(msg, e).setFatal();
                }
                catch (ClassNotFoundException e)
                {
                    String msg = "ClassNotFoundException: error when creating object";
                    NucleusLogger.DATASTORE.error(msg);
                    throw new NucleusUserException(msg, e).setFatal();
                }
            }
        }
        catch (SQLException sqle)
        {
            throw new NucleusDataStoreException(LOCALISER.msg("055002", "Object", "" + param, column, sqle.getMessage()), sqle);
        }

        return obj;
    }

    /**
     * @see org.datanucleus.store.rdbms.mapping.datastore.AbstractDatastoreMapping#getString(ResultSet, int)
     */
    public String getString(ResultSet resultSet, int exprIndex)
    {
        return (String)getObject(resultSet, exprIndex);
    }

    /**
     * @see org.datanucleus.store.rdbms.mapping.datastore.AbstractDatastoreMapping#getTypeInfo()
     */
    public SQLTypeInfo getTypeInfo()
    {
        return storeMgr.getSQLTypeInfoForJDBCType(Types.BLOB);
    }

    /**
     * @see org.datanucleus.store.rdbms.mapping.datastore.AbstractDatastoreMapping#getUpdateInputParameter()
     */
    public String getUpdateInputParameter()
    {
        return "EMPTY_BLOB()";
    }

    /**
     * Whether to include this mapping in a fetch statement.
     * @return Whether to include it when fetching the object
     */
    public boolean includeInSQLFetchStatement()
    {
        return true;
    }

    /**
     * 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
     * 
     * SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE
     * 
* and then updates the Blob value returned. * @param sm 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 * @throws NucleusDataStoreException */ @SuppressWarnings("deprecation") public static void updateBlobColumn(ObjectProvider sm, Table table, DatastoreMapping mapping, byte[] bytes) { ExecutionContext ec = sm.getExecutionContext(); RDBMSStoreManager storeMgr = table.getStoreManager(); DatastoreClass classTable = (DatastoreClass)table; // Don't support join tables yet SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory(); // Generate "SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE" statement SQLStatement sqlStmt = new SQLStatement(storeMgr, table, null, null); sqlStmt.setClassLoaderResolver(ec.getClassLoaderResolver()); sqlStmt.addExtension("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 = sm.getClassMetaData(); int inputParamNum = 1; if (cmd.getIdentityType() == IdentityType.DATASTORE) { // Datastore identity value for input JavaTypeMapping datastoreIdMapping = classTable.getDatastoreObjectIdMapping(); 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(StatementClassMapping.MEMBER_DATASTORE_ID); if (datastoreIdx == null) { datastoreIdx = new StatementMappingIndex(datastoreIdMapping); mappingDefinition.addMappingForMember(StatementClassMapping.MEMBER_DATASTORE_ID, 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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy