Package org.jpox.store.rdbms.mapping.oracle

Source Code of org.jpox.store.rdbms.mapping.oracle.OracleClobRDBMSMapping

/**********************************************************************
Copyright (c) 2004 Erik Bengtson 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:
2004 Andy Jefferson - localised messages
2005 Andrew Hoffman - changed mapping parent class
2006 Andy Jefferson - add convenience method for updating CLOB
    ...
**********************************************************************/
package org.jpox.store.rdbms.mapping.oracle;

import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.jpox.ManagedConnection;
import org.jpox.ObjectManager;
import org.jpox.StateManager;
import org.jpox.exceptions.JPOXDataStoreException;
import org.jpox.exceptions.JPOXObjectNotFoundException;
import org.jpox.store.mapped.DatastoreContainerObject;
import org.jpox.store.mapped.DatastoreField;
import org.jpox.store.mapped.DatastoreFieldDefinitionException;
import org.jpox.store.mapped.FetchStatement;
import org.jpox.store.mapped.MappedStoreManager;
import org.jpox.store.mapped.mapping.DatastoreMapping;
import org.jpox.store.mapped.mapping.JavaTypeMapping;
import org.jpox.store.mapped.mapping.Mappings;
import org.jpox.store.rdbms.Column;
import org.jpox.store.rdbms.RDBMSFetchStatement;
import org.jpox.store.rdbms.RDBMSManager;
import org.jpox.store.rdbms.SQLController;
import org.jpox.store.rdbms.adapter.DatabaseAdapter;
import org.jpox.store.rdbms.mapping.ClobRDBMSMapping;
import org.jpox.store.rdbms.typeinfo.TypeInfo;
import org.jpox.util.Localiser;

/**
* Mapping for Oracle CLOB type.
*
* @version $Revision: 1.27 $
**/
public class OracleClobRDBMSMapping extends ClobRDBMSMapping
{
    /** Localiser for messages. */
    protected static final Localiser LOCALISER_RDBMS = Localiser.getInstance("org.jpox.store.rdbms.Localisation",
        RDBMSManager.class.getClassLoader());

    /**
     * Constructor
     * @param storeMgr Store Manager
     * @param mapping The Java type mapping
     */
    protected OracleClobRDBMSMapping(MappedStoreManager storeMgr, JavaTypeMapping mapping)
    {
        super(storeMgr, mapping);
    }
   
    /**
     * Constructor.
     * @param mapping The java type mapping for the field.
     * @param storeMgr Manager for the store
     * @param field The field
     */
    public OracleClobRDBMSMapping(JavaTypeMapping mapping, MappedStoreManager storeMgr, DatastoreField field)
    {
    super(storeMgr, mapping);
    column = (Column) field;
    initialize();
  }

    private void initialize()
    {
        if (column != null && !column.isUnlimitedLength())
        {
            throw new DatastoreFieldDefinitionException("Invalid length specified for CLOB column " + column + ", must be 'unlimited'");
        }
    initTypeInfo();
    }

    public TypeInfo getTypeInfo()
    {
        return getDatabaseAdapter().getTypeInfo(Types.CLOB);
    }

    public String getInsertionInputParameter()
    {
        return "EMPTY_CLOB()";
    }
   
    public boolean includeInFetchStatement()
    {
        return true;
    }

    public String getUpdateInputParameter()
    {
        return "EMPTY_CLOB()";
    }

    /**
     * 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_CLOB()" above so dont put value in
        return false;
    }

    public String getString(Object rs, int param)
    {
        String value = null;

        try
        {
            char[] cbuf = null;
            java.sql.Clob clob = ((ResultSet) rs).getClob(param);

            if (clob != null)
            {
                // Note: Using clob.stringValue() results in StoreManagerTest
                // exception: "java.sql.SQLException: Conversion to String failed"

                StringBuffer sbuf = new StringBuffer();
                InputStreamReader reader = new InputStreamReader(clob.getAsciiStream());

                try
                {
                    final int BUFF_SIZE = 4096;
                    cbuf = new char[BUFF_SIZE];
                    int charsRead = reader.read(cbuf);

                    while (-1 != charsRead)
                    {
                        sbuf.append(cbuf, 0, charsRead);

                        java.util.Arrays.fill(cbuf, (char)0);
                        charsRead = reader.read(cbuf);
                    }

                }
                catch (IOException e)
                {
                    throw new JPOXDataStoreException("Error reading Oracle CLOB object: param = " + param, e);
                }

                value = sbuf.toString();

                if (value.length() == 0)
                {
                    value = null;
                }
                else if (value.equals(getDatabaseAdapter().getSurrogateForEmptyStrings()))
                {
                    value = "";
                }
            }
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException(LOCALISER.msg("RDBMSMapping.UnableToGetParam","String", "" + param), e);
        }

        return value;
    }

    public Object getObject(Object rs, int param)
    {
        return getString(rs, param);
    }
    /**
     * Convenience method to update the contents of a CLOB column.
     * Oracle requires that a CLOB is initialised with EMPTY_CLOB() and then you retrieve
     * the column and update its CLOB value. Performs a statement
     * <pre>
     * SELECT {clobColumn} FROM TABLE WHERE ID=? FOR UPDATE
     * </pre>
     * and then updates the Clob value returned.
     * @param sm StateManager of the object
     * @param datastoreContainer Table storing the CLOB column
     * @param mapping Datastore mapping for the CLOB column
     * @param value The value to store in the CLOB
     * @throws JPOXObjectNotFoundException
     * @throws JPOXDataStoreException
     */
    public static void updateClobColumn(StateManager sm,
            DatastoreContainerObject datastoreContainer,
            DatastoreMapping mapping,
            String value)
    {
        // Generate "SELECT {clobColumn} FROM TABLE WHERE ID=? FOR UPDATE" statement
        FetchStatement fetchStmt = new RDBMSFetchStatement(datastoreContainer);
        fetchStmt.select(mapping.getDatastoreField());
        JavaTypeMapping idMapping = datastoreContainer.getIDMapping();
        for (int i = 0; i < idMapping.getNumberOfDatastoreFields(); i++)
        {
            fetchStmt.andCondition(fetchStmt.referenceDatastoreField(idMapping.getDataStoreMapping(i).getDatastoreField()) + " = ?");
        }
        String textStmt = fetchStmt.toString(true);

        if (sm.getPcObjectType() != StateManager.PC)
        {
            // This mapping is embedded, so navigate back to the real owner since that is the "id" in the table
            StateManager[] embeddedOwners = sm.getEmbeddedOwners();
            if (embeddedOwners != null)
            {
                // Just use the first owner
                // TODO Should check if the owner is stored in this table
                sm = embeddedOwners[0];
            }
        }

        try
        {
            ObjectManager om = sm.getObjectManager();
            RDBMSManager storeMgr = (RDBMSManager)om.getStoreManager();
            ManagedConnection mconn = storeMgr.getConnection(om);
            SQLController sqlControl = storeMgr.getSQLController();

            try
            {
                PreparedStatement ps = sqlControl.getStatementForQuery(mconn, textStmt);

                try
                {
                    Object pcObject = sm.getObject();
                    idMapping.setObject(om, ps, Mappings.getParametersIndex(1, idMapping), pcObject);

                    ResultSet rs = sqlControl.executeStatementQuery(mconn, textStmt, ps);
                    try
                    {
                        if (!rs.next())
                        {
                            throw new JPOXObjectNotFoundException("No such database row", sm.getInternalObjectId());
                        }

                        int jdbcMajorVersion = ((DatabaseAdapter)datastoreContainer.getStoreManager().getDatastoreAdapter()).getDriverMajorVersion();
                        if (jdbcMajorVersion < 10)
                        {
                            // Oracle JDBC drivers version 9 and below use some sh*tty Oracle-specific CLOB type
                            // we have to cast to that, face west, pray whilst saying ommmmmmmmmmm
                            oracle.sql.CLOB clob = (oracle.sql.CLOB)rs.getClob(1);
                            if (clob != null)
                            {
                                clob.putString(1, value);
                            }
                        }
                        else
                        {
                            // Oracle JDBC drivers 10 and above supposedly use the JDBC standard class for Clobs
                            java.sql.Clob clob = rs.getClob(1);
                            if (clob != null)
                            {
                                clob.setString(1, value);
                            }
                        }
                    }
                    finally
                    {
                        rs.close();
                    }
                }
                finally
                {
                    sqlControl.closeStatement(mconn, ps);
                }
            }
            finally
            {
                mconn.release();
            }
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException("Update of CLOB value failed: " + textStmt, e);
        }
    }
}
TOP

Related Classes of org.jpox.store.rdbms.mapping.oracle.OracleClobRDBMSMapping

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.