db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From arm...@apache.org
Subject svn commit: r489836 - in /db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms: PlatformOracle9iImpl.java PlatformOracleImpl.java
Date Sat, 23 Dec 2006 02:40:42 GMT
Author: arminw
Date: Fri Dec 22 18:40:42 2006
New Revision: 489836

URL: http://svn.apache.org/viewvc?view=rev&rev=489836
Log:
refactored version

Modified:
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracle9iImpl.java
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracleImpl.java

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracle9iImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracle9iImpl.java?view=diff&rev=489836&r1=489835&r2=489836
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracle9iImpl.java
(original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracle9iImpl.java
Fri Dec 22 18:40:42 2006
@@ -18,18 +18,20 @@
 import java.io.ByteArrayInputStream;
 import java.lang.reflect.Method;
 import java.sql.Connection;
-import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Types;
+import java.sql.PreparedStatement;
 import java.util.Collections;
 import java.util.Map;
 import java.util.WeakHashMap;
 
+import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.ojb.broker.metadata.ConnectionPoolDescriptor;
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
 import org.apache.ojb.broker.util.ClassHelper;
 import org.apache.ojb.broker.util.UnwrapHelper;
+import org.apache.ojb.broker.util.ConvertHelper;
 import org.apache.ojb.broker.util.logging.Logger;
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 
@@ -56,9 +58,6 @@
  * TODO: Optimization: use ROWNUM to minimize the effects of not having server side cursors
  * see http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:127412348064
  *
- * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird</a>
- * @author <a href="mailto:mkalen@apache.org">Martin Kal&eacute;n</a>
- * @author Contributions from: Erik Forkalsrud, Danilo Tommasina, Thierry Hanot, Don Lyon
  * @version CVS $Id$
  * @see Platform
  * @see PlatformDefaultImpl
@@ -66,8 +65,54 @@
  */
 public class PlatformOracle9iImpl extends PlatformOracleImpl
 {
-    private Logger logger = LoggerFactory.getLogger(PlatformOracle9iImpl.class);
+    private static Logger log = LoggerFactory.getLogger(PlatformOracle9iImpl.class);
+
+    /**
+     * Platform attribute of Oracle's native statement cache pool.
+     */
+    protected static final String ATTRIBUTE_STATEMENT_CACHE_SIZE = "platform.oracle.statementCacheSize";
+    /**
+     * Platform attribute of Oracle's native prefetch handling.
+     */
+    protected static final String ATTRIBUTE_PREFETCH_SIZE = "platform.oracle.prefetchSize";
+    /**
+     * Platform attribute to enable Oracle's native batch handling.
+     */
+    protected static final String ATTRIBUTE_BATCH_SIZE = "platform.oracle.batchSize";
+
+    protected static final Class[] PARAM_TYPE_EMPTY = {};
+    protected static final Class[] PARAM_TYPE_INTEGER = {Integer.TYPE};
+    protected static final Class[] PARAM_TYPE_BOOLEAN = {Boolean.TYPE};
+    protected static final Class[] PARAM_TYPE_STRING = {String.class};
+    protected static final Object[] PARAM_EMPTY = new Object[]{};
+    protected static final Object[] PARAM_BOOLEAN_TRUE = new Object[]{Boolean.TRUE};
+
+    protected static String JBOSS_CONN_NAME = "org.jboss.resource.adapter.jdbc.WrappedConnection";
+    protected static String ORA_CONNECTION_CLASS_NAME = "oracle.jdbc.OracleConnection";
+    protected static String ORA_STATEMENT_CLASS_NAME = "oracle.jdbc.OraclePreparedStatement";
+
+    protected Class JBOSS_CONN_CLASS;
+    protected Class ORA_CONN_CLASS;
+    protected Class ORA_PS_CLASS;
+    protected Class ORA_CLOB_CLASS;
+    protected Class ORA_BLOB_CLASS;
+    protected Class[] PARAM_TYPE_INT_ORACLOB;
+    protected Class[] PARAM_TYPE_INT_ORABLOB;
+    protected Method METHOD_SET_STATEMENT_CACHE_SIZE;
+    protected Method METHOD_SET_IMPLICIT_CACHING_ENABLED;
+    protected Method METHOD_SET_ROW_PREFETCH;
+    protected Method METHOD_SET_BLOB;
+    protected Method METHOD_SET_CLOB;
+    protected boolean oraStatementCachingAvailable;
+    protected boolean oraRowPrefetchAvailable;
+    protected boolean oraLobHandlingAvailable;
+    protected boolean oraBatchAvailable;
 
+    protected static Map m_batchStatementsInProgress = Collections.synchronizedMap(new WeakHashMap());
+    /**
+     * Size of Oracle's native batch handling size.
+     */
+    protected Object[] paramStatementBatchSize;
     /**
      * Number of cached statements per connection,
      * when using implicit caching with OracleConnections.
@@ -75,7 +120,7 @@
      * @see <a href="http://www.apache.org/~mkalen/ojb/broker-tests.html">Profiling
page</a>
      * for a discussion re sizing
      */
-    protected static final int STATEMENT_CACHE_SIZE = 10;
+    protected Object[] paramStatementCacheSize;
     /**
      * Number of rows pre-fetched by the JDBC-driver for each executed query,
      * when using Oracle row pre-fetching with OracleConnections.
@@ -85,43 +130,7 @@
      * connection-pool attribute with name="jdbc.defaultRowPrefetch".
      * Oracle JDBC-driver default value=10.
      */
-    protected static final int ROW_PREFETCH_SIZE = 20;
-
-    // From Oracle9i JDBC Developer's Guide and Reference:
-    // "Batch values between 5 and 30 tend to be the most effective."
-    protected static final int STATEMENTS_PER_BATCH = 20;
-    protected static Map m_batchStatementsInProgress = Collections.synchronizedMap(new WeakHashMap(STATEMENTS_PER_BATCH));
-
-    protected static final Class[] PARAM_TYPE_EMPTY = {};
-    protected static final Class[] PARAM_TYPE_INTEGER = {Integer.TYPE};
-    protected static final Class[] PARAM_TYPE_BOOLEAN = {Boolean.TYPE};
-    protected static final Class[] PARAM_TYPE_STRING = {String.class};
-
-    protected static final Object[] PARAM_EMPTY = new Object[]{};
-    protected static final Object[] PARAM_STATEMENT_CACHE_SIZE = new Object[]{new Integer(STATEMENT_CACHE_SIZE)};
-    protected static final Object[] PARAM_ROW_PREFETCH_SIZE = new Object[]{new Integer(ROW_PREFETCH_SIZE)};
-    protected static final Object[] PARAM_STATEMENT_BATCH_SIZE = new Object[]{new Integer(STATEMENTS_PER_BATCH)};
-    protected static final Object[] PARAM_BOOLEAN_TRUE = new Object[]{Boolean.TRUE};
-
-    protected static final String JBOSS_CONN_NAME =
-            "org.jboss.resource.adapter.jdbc.WrappedConnection";
-    protected static Class JBOSS_CONN_CLASS = null;
-
-    protected static Class ORA_CONN_CLASS;
-    protected static Class ORA_PS_CLASS;
-    protected static Class ORA_CLOB_CLASS;
-    protected static Class ORA_BLOB_CLASS;
-    protected static Class[] PARAM_TYPE_INT_ORACLOB;
-    protected static Class[] PARAM_TYPE_INT_ORABLOB;
-    protected static Method METHOD_SET_STATEMENT_CACHE_SIZE;
-    protected static Method METHOD_SET_IMPLICIT_CACHING_ENABLED;
-    protected static Method METHOD_SET_ROW_PREFETCH;
-    protected static Method METHOD_SET_BLOB = null;
-    protected static Method METHOD_SET_CLOB = null;
-    protected static boolean ORA_STATEMENT_CACHING_AVAILABLE;
-    protected static boolean ORA_ROW_PREFETCH_AVAILABLE;
-    protected static boolean ORA_CLOB_HANDLING_AVAILABLE;
-    protected static boolean ORA_BLOB_HANDLING_AVAILABLE;
+    protected Object[] paramRowPrefetchSize;
 
     /**
      * Helper to unwrap connections and statements.
@@ -129,97 +138,251 @@
     protected UnwrapHelper unwrapHelper;
 
 
-    /**
-     * Default constructor.
-     */
-    public PlatformOracle9iImpl()
+    public PlatformOracle9iImpl(JdbcConnectionDescriptor jcd)
     {
-        super();
+        super(jcd);
+        initOracleReflectedVars();
     }
 
     /**
-     * Enables Oracle statement caching and row prefetching if supported by the JDBC-driver.
-     * @param jcd the OJB <code>JdbcConnectionDescriptor</code> (metadata) for
the connection to be initialized
-     * @param conn the <code>Connection</code>-object (physical) to be initialized
-     * @see PlatformDefaultImpl#initializeJdbcConnection
-     * @see <a href="http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/jdbc30/StmtCacheSample/Readme.html">
-     * Oracle TechNet Statement Caching Sample</a>
-     * @see <a href="http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/advanced/RowPrefetchSample/Readme.html">
-     * Oracle TechNet Row Pre-fetch Sample<a>
+     * Initializes static variables needed for Oracle-extensions and large BLOB/CLOB support,
+     * attributes set in {@link org.apache.ojb.broker.metadata.JdbcConnectionDescriptor}.
      */
-    public void initializeJdbcConnection(final JdbcConnectionDescriptor jcd,
-                                         final Connection conn)
-            throws PlatformException
+    private void initOracleReflectedVars()
     {
-        // Do all the generic initialization in PlatformDefaultImpl first
-        super.initializeJdbcConnection(jcd, conn);
+        unwrapHelper = new UnwrapHelper();
+        try
+        {
+            /*
+            Check for Oracle-specific classes, OracleConnection-specific
+            statement caching/row pre-fetch methods and Oracle BLOB/CLOB access methods.
+            We can do this in constructor in spite of possible mixing of instance being
+            able vs unable passed at runtime (since withouth these classes and methods
+            it's impossible to enable ORA-extensions at all even if instances are capable).
+            */
+            ORA_CONN_CLASS = ClassHelper.getClass(ORA_CONNECTION_CLASS_NAME, false);
+            ORA_PS_CLASS = ClassHelper.getClass(ORA_STATEMENT_CLASS_NAME, false);
+            /*
+            The unwrap pattern used in {@link org.apache.ojb.broker.util.UnwrapHelper}
+            to unwrap connection instance to Oracle's specific connection implementation
class.
+            */
+            Object[] oracleUnwrapPattern = new Object[] {"oracle 10g", UnwrapHelper.TYPE_METHOD,
+                    new Class[]{ORA_CONN_CLASS}, "unwrapCompletely", null, null, null};
+            // add the oracle unwrap pattern
+            unwrapHelper.addUnwrapPattern(oracleUnwrapPattern);
+        }
+        catch(ClassNotFoundException e)
+        {
+            log.info("Can't access Oracle specific driver Connection/Statement classes",
e);
+        }
+
 
-        // Check for managed environments known to reject Oracle extension at this level
-        // (saves us from trying to unwrap just to catch exceptions next)
-        final Class connClass = conn.getClass();
-        if (JBOSS_CONN_CLASS != null && JBOSS_CONN_CLASS.isAssignableFrom(connClass))
+        try
         {
-            if (logger.isDebugEnabled())
-            {
-                logger.debug("JBoss detected, Oracle Connection tuning left to J2EE container.");
-            }
-            return;
+            ORA_CLOB_CLASS = ClassHelper.getClass("oracle.sql.CLOB", false);
+            ORA_BLOB_CLASS = ClassHelper.getClass("oracle.sql.BLOB", false);
+            PARAM_TYPE_INT_ORACLOB = new Class[]{ Integer.TYPE, ORA_CLOB_CLASS };
+            PARAM_TYPE_INT_ORABLOB = new Class[]{ Integer.TYPE, ORA_BLOB_CLASS };
+            METHOD_SET_CLOB = ClassHelper.getMethod(ORA_PS_CLASS, "setCLOB", PARAM_TYPE_INT_ORACLOB);
+            METHOD_SET_BLOB = ClassHelper.getMethod(ORA_PS_CLASS, "setBLOB", PARAM_TYPE_INT_ORABLOB);
+        }
+        catch(ClassNotFoundException e)
+        {
+            log.info("Can't use Oracle specific BLOB/CLOB classes", e);
         }
 
-        // Check if this is a wrapped connection and if so unwrap it
-        final Connection oraConn = unwrapConnection(conn);
-        if (oraConn == null)
+        try
         {
-            return;
+            METHOD_SET_STATEMENT_CACHE_SIZE =
+                    ClassHelper.getMethod(ORA_CONN_CLASS, "setStatementCacheSize", PARAM_TYPE_INTEGER);
+            METHOD_SET_IMPLICIT_CACHING_ENABLED =
+                    ClassHelper.getMethod(ORA_CONN_CLASS, "setImplicitCachingEnabled", PARAM_TYPE_BOOLEAN);
         }
+        catch(Exception e)
+        {
+            log.info("Can't enable Oracle specific implicit statement caching", e);
+        }
+
 
-        // At this point we know that we have an OracleConnection instance and can thus
-        // try to invoke methods via reflection (if available)
-        if (ORA_STATEMENT_CACHING_AVAILABLE)
+        try
         {
-            try
+            METHOD_SET_ROW_PREFETCH = ClassHelper.getMethod(ORA_CONN_CLASS, "setDefaultRowPrefetch",
PARAM_TYPE_INTEGER);
+        }
+        catch(Exception e)
+        {
+            log.info("Can't use Oracle specific row prefetch settings", e);
+        }
+
+        oraStatementCachingAvailable = METHOD_SET_STATEMENT_CACHE_SIZE != null &&
METHOD_SET_IMPLICIT_CACHING_ENABLED != null;
+        oraRowPrefetchAvailable = METHOD_SET_ROW_PREFETCH != null;
+        oraLobHandlingAvailable = METHOD_SET_CLOB != null && METHOD_SET_BLOB != null;
+
+        if(oraStatementCachingAvailable)
+        {
+            String stmtCacheSize = jcd.getAttribute(ATTRIBUTE_STATEMENT_CACHE_SIZE);
+            boolean enabled = false;
+            if(stmtCacheSize != null && stmtCacheSize.length() > 0)
             {
-                // Set number of cached statements and enable implicit caching
-                METHOD_SET_STATEMENT_CACHE_SIZE.invoke(oraConn, PARAM_STATEMENT_CACHE_SIZE);
-                METHOD_SET_IMPLICIT_CACHING_ENABLED.invoke(oraConn, PARAM_BOOLEAN_TRUE);
+                try
+                {
+                    Integer size = ConvertHelper.toInteger(stmtCacheSize);
+                    if(size.intValue() > 0)
+                    {
+                        paramStatementCacheSize = new Object[]{size};
+                        enabled = true;
+                    }
+                }
+                catch(NumberFormatException e)
+                {
+                    log.error("Can't enable Oracle's statement caching, illegal value for
attribute: "
+                            + ATTRIBUTE_STATEMENT_CACHE_SIZE + "=" + stmtCacheSize);
+                }
             }
-            catch (Exception e)
+            if(!enabled)
+            {
+                oraStatementCachingAvailable = false;
+                log.info("Oracle's statement caching not used: "+ ATTRIBUTE_STATEMENT_CACHE_SIZE
+ "=" + stmtCacheSize);
+            }
+            else
+            {
+                log.info("Prepared to use Oracle's statement caching: "+ ATTRIBUTE_STATEMENT_CACHE_SIZE
+ "=" + stmtCacheSize);
+            }
+        }
+
+        if(oraRowPrefetchAvailable)
+        {
+            String prefetchSize = jcd.getAttribute(ATTRIBUTE_PREFETCH_SIZE);
+            boolean enabled = false;
+            if(prefetchSize != null && prefetchSize.length() > 0)
             {
-                if (logger.isDebugEnabled())
+                try
+                {
+                    Integer size = ConvertHelper.toInteger(prefetchSize);
+                    if(size.intValue() > 0)
+                    {
+                        paramRowPrefetchSize = new Object[]{size};
+                        enabled = true;
+                    }
+                }
+                catch(NumberFormatException e)
                 {
-                    logger.debug("PlatformOracle9iImpl could not enable Oracle statement
caching."
-                                 + " Original/unwrapped connection classes="
-                                 + connClass.getName() + "/" + oraConn.getClass().getName());
+                    log.error("Can't enable Oracle's row prefetching, illegal value for attribute:
"
+                            + ATTRIBUTE_PREFETCH_SIZE + "=" + prefetchSize);
                 }
             }
+            if(!enabled)
+            {
+                oraRowPrefetchAvailable = false;
+                log.info("Oracle's row prefetching not used: " + ATTRIBUTE_PREFETCH_SIZE
+ "=" + prefetchSize);
+            }
+            else
+            {
+                log.info("Prepared to use Oracle's row prefetching: " + ATTRIBUTE_PREFETCH_SIZE
+ "=" + prefetchSize);
+            }
         }
 
-        /*
-        mkalen: Note from the Oracle documentation:
-            Do not mix the JDBC 2.0 fetch size API and the Oracle row prefetching API
-            in your application. You can use one or the other, but not both.
-        */
-        final ConnectionPoolDescriptor cpd = jcd.getConnectionPoolDescriptor();
-        final int cpdFetchSizeHint = cpd.getFetchSize();
-        if (cpdFetchSizeHint == 0 && ORA_ROW_PREFETCH_AVAILABLE)
+        String batchSize = jcd.getAttribute(ATTRIBUTE_BATCH_SIZE);
+        boolean enabled = false;
+        if(batchSize != null && batchSize.length() > 0)
         {
             try
             {
-                final String prefetchFromJcd;
-                prefetchFromJcd = cpd.getJdbcProperties().getProperty("defaultRowPrefetch");
-                if (prefetchFromJcd == null)
+                Integer size = ConvertHelper.toInteger(batchSize);
+                if(size.intValue() > 0)
                 {
-                    METHOD_SET_ROW_PREFETCH.invoke(oraConn, PARAM_ROW_PREFETCH_SIZE);
+                    paramStatementBatchSize = new Object[]{size};
+                    enabled = true;
                 }
-                // Else, number of prefetched rows were set via Properties on Connection
             }
-            catch (Exception e)
+            catch(NumberFormatException e)
             {
-                if (logger.isDebugEnabled())
+                log.error("Can't enable Oracle's native batching, illegal value for attribute:
"
+                        + ATTRIBUTE_BATCH_SIZE + "=" + batchSize);
+            }
+        }
+        if(!enabled)
+        {
+            oraBatchAvailable = false;
+            log.info("Oracle's native batching not used: " + ATTRIBUTE_BATCH_SIZE + "=" +
batchSize);
+        }
+        else
+        {
+            log.info("Prepared to use Oracle's native batching: " + ATTRIBUTE_BATCH_SIZE
+ "=" + batchSize);
+        }
+    }
+
+    /**
+     * Enables Oracle statement caching and row prefetching if supported by the JDBC-driver.
+     * @param conn the <code>Connection</code>-object (physical) to be initialized
+     * @see PlatformDefaultImpl#initializeJdbcConnection
+     * @see <a href="http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/jdbc30/StmtCacheSample/Readme.html">
+     * Oracle TechNet Statement Caching Sample</a>
+     * @see <a href="http://otn.oracle.com/sample_code/tech/java/sqlj_jdbc/files/advanced/RowPrefetchSample/Readme.html">
+     * Oracle TechNet Row Pre-fetch Sample<a>
+     */
+    public void initializeJdbcConnection(final Connection conn) throws PlatformException
+    {
+        // Do all the generic initialization in PlatformDefaultImpl first
+        super.initializeJdbcConnection(conn);
+
+        Connection oraConn = null;
+        if(oraStatementCachingAvailable || oraRowPrefetchAvailable)
+        {
+            oraConn = unwrapConnection(conn);
+        }
+        if(oraConn != null)
+        {
+            final Class connClass = conn.getClass();
+            if(oraRowPrefetchAvailable)
+            {
+                /*
+                mkalen: Note from the Oracle documentation:
+                Do not mix the JDBC 2.0 fetch size API and the Oracle row prefetching API
+                in your application. You can use one or the other, but not both.
+                */
+                final ConnectionPoolDescriptor cpd = jcd.getConnectionPoolDescriptor();
+                if (cpd.getFetchSize() == 0)
                 {
-                    logger.debug("PlatformOracle9iImpl could not enable Oracle row pre-fetching."
-                                 + "Original/unwrapped connection classes="
-                                 + connClass.getName() + "/" + oraConn.getClass().getName());
+                    try
+                    {
+                        final String prefetchFromJcd = cpd.getJdbcProperties().getProperty("defaultRowPrefetch");
+                        if (prefetchFromJcd == null)
+                        {
+                            METHOD_SET_ROW_PREFETCH.invoke(oraConn, paramRowPrefetchSize);
+                            if(log.isDebugEnabled()) log.debug("Oracle's native row prefetching
enabled for connection " + conn);
+                        }
+                        // Else, number of prefetched rows were set via Properties on Connection
+                    }
+                    catch (Exception e)
+                    {
+                        if (log.isDebugEnabled())
+                        {
+                            log.debug("PlatformOracle9iImpl could not enable Oracle row pre-fetching."
+                                         + "Original/unwrapped connection classes="
+                                         + connClass.getName() + "/" + oraConn.getClass().getName(),
e);
+                        }
+                    }
+                }
+            }
+            if(oraStatementCachingAvailable)
+            {
+                // At this point we know that we have an OracleConnection instance and can
thus
+                // try to invoke methods via reflection (if available)
+                try
+                {
+                    // Set number of cached statements and enable implicit caching
+                    METHOD_SET_STATEMENT_CACHE_SIZE.invoke(oraConn, paramStatementCacheSize);
+                    METHOD_SET_IMPLICIT_CACHING_ENABLED.invoke(oraConn, PARAM_BOOLEAN_TRUE);
+                    if(log.isDebugEnabled()) log.debug("Oracle's native implicit statement
caching enabled for connection " + conn);
+                }
+                catch (Exception e)
+                {
+                    if (log.isDebugEnabled())
+                    {
+                        log.debug("PlatformOracle9iImpl could not enable Oracle statement
caching."
+                                     + " Original/unwrapped connection classes="
+                                     + connClass.getName() + "/" + oraConn.getClass().getName());
+                    }
                 }
             }
         }
@@ -246,24 +409,29 @@
      */
     public void beforeBatch(PreparedStatement stmt) throws PlatformException
     {
-        // Check for Oracle batching support
-        final Method methodSetExecuteBatch;
-        final Method methodSendBatch;
-        methodSetExecuteBatch = ClassHelper.getMethod(stmt, "setExecuteBatch", PARAM_TYPE_INTEGER);
-        methodSendBatch = ClassHelper.getMethod(stmt, "sendBatch", null);
-
-        final boolean statementBatchingSupported = methodSetExecuteBatch != null &&
methodSendBatch != null;
-        if (statementBatchingSupported)
+        if (oraBatchAvailable)
         {
-            try
+            // Check for Oracle batching support
+            final Method methodSetExecuteBatch;
+            final Method methodSendBatch;
+            methodSetExecuteBatch = ClassHelper.getMethod(stmt, "setExecuteBatch", PARAM_TYPE_INTEGER);
+            methodSendBatch = ClassHelper.getMethod(stmt, "sendBatch", null);
+            if(methodSetExecuteBatch != null && methodSendBatch != null)
             {
-                // Set number of statements per batch
-                methodSetExecuteBatch.invoke(stmt, PARAM_STATEMENT_BATCH_SIZE);
-                m_batchStatementsInProgress.put(stmt, methodSendBatch);
+                try
+                {
+                    // Set number of statements per batch
+                    methodSetExecuteBatch.invoke(stmt, paramStatementBatchSize);
+                    m_batchStatementsInProgress.put(stmt, methodSendBatch);
+                }
+                catch (Exception e)
+                {
+                    throw new PlatformException(e.getLocalizedMessage(), e);
+                }
             }
-            catch (Exception e)
+            else
             {
-                throw new PlatformException(e.getLocalizedMessage(), e);
+                super.beforeBatch(stmt);
             }
         }
         else
@@ -281,8 +449,7 @@
     public void addBatch(PreparedStatement stmt) throws PlatformException
     {
         // Check for Oracle batching support
-        final boolean statementBatchingSupported = m_batchStatementsInProgress.containsKey(stmt);
-        if (statementBatchingSupported)
+        if (m_batchStatementsInProgress.containsKey(stmt))
         {
             try
             {
@@ -325,6 +492,8 @@
             }
             catch (Exception e)
             {
+                log.error("Error when invoke batch statement", e);
+                e = (Exception) ExceptionUtils.getRootCause(e);
                 throw new PlatformException(e.getLocalizedMessage(), e);
             }
         }
@@ -346,9 +515,7 @@
         {
             oraStmt = unwrapStatement(ps);
             oraConn = unwrapConnection(ps.getConnection());
-            oraLargeLobSupportAvailable =
-                    oraStmt != null && oraConn != null &&
-                    (sqlType == Types.CLOB ? ORA_CLOB_HANDLING_AVAILABLE : ORA_BLOB_HANDLING_AVAILABLE);
+            oraLargeLobSupportAvailable = oraStmt != null && oraConn != null &&
oraLobHandlingAvailable;
         }
         else
         {
@@ -365,20 +532,6 @@
             super.changePreparedStatementResultSetType(ps);
             ps.setBinaryStream(index, inputStream, buf.length);
         }
-        else if (value instanceof Double)
-        {
-            // workaround for the bug in Oracle thin driver
-            ps.setDouble(index, ((Double) value).doubleValue());
-        }
-        else if (sqlType == Types.BIGINT && value instanceof Integer)
-        {
-            // workaround: Oracle thin driver problem when expecting long
-            ps.setLong(index, ((Integer) value).intValue());
-        }
-        else if (sqlType == Types.INTEGER && value instanceof Long)
-        {
-            ps.setLong(index, ((Long) value).longValue());
-        }
         else if (sqlType == Types.CLOB && oraLargeLobSupportAvailable &&
value instanceof String)
         {
             // TODO: If using Oracle update batching with the thin driver, throw exception
on 4k limit
@@ -427,20 +580,24 @@
      * @param conn the connection to unwrap (if needed)
      * @return OracleConnection or null if not able to unwrap
      */
-    protected Connection unwrapConnection(Connection conn)
+    protected Connection unwrapConnection(final Connection conn)
     {
-        final Connection unwrapped = unwrapHelper.unwrapConnection(ORA_CONN_CLASS, conn);
-        if (unwrapped == null)
+        Connection result = conn;
+        if(conn != null)
         {
-            // mkalen:  only log this as debug since it will be logged for every connection
-            //          (ie only useful during development).
-            if (logger.isDebugEnabled())
+            result = unwrapHelper.unwrapConnection(ORA_CONN_CLASS, conn);
+            if (result == null)
             {
-                logger.debug("PlatformOracle9iImpl could not unwrap " + conn.getClass().getName()
+
-                             ", Oracle-extensions disabled.");
+                // mkalen:  only log this as debug since it will be logged for every connection
+                //          (ie only useful during development).
+                if (log.isDebugEnabled())
+                {
+                    log.debug("PlatformOracle9iImpl could not unwrap connection: " + conn.getClass()
+
+                                 ", can't use Oracle's native Connection extensions.");
+                }
             }
         }
-        return unwrapped;
+        return result;
     }
 
     /**
@@ -448,81 +605,23 @@
      * @param ps the PreparedStatement to unwrap (if needed)
      * @return OraclePreparedStatement or null if not able to unwrap
      */
-    protected Statement unwrapStatement(Statement ps)
+    protected Statement unwrapStatement(final Statement ps)
     {
-        final Statement unwrapped = unwrapHelper.unwrapStatement(ORA_PS_CLASS, ps);
-        if (unwrapped == null)
+        Statement result = ps;
+        if(ps != null)
         {
-            // mkalen:  only log this as debug since it will be logged for every connection
-            //          (ie only useful during development).
-            if (logger.isDebugEnabled())
+            result = unwrapHelper.unwrapStatement(ORA_PS_CLASS, ps);
+            if (result == null)
             {
-                logger.debug("PlatformOracle9iImpl could not unwrap " + ps.getClass().getName()
+
-                             ", large CLOB/BLOB support disabled.");
+                // mkalen:  only log this as debug since it will be logged for every connection
+                //          (ie only useful during development).
+                if (log.isDebugEnabled())
+                {
+                    log.debug("PlatformOracle9iImpl could not unwrap statement: " + ps.getClass()
+
+                                 ", can't use Oracle's native Statement extensions.");
+                }
             }
         }
-        return unwrapped;
+        return result;
     }
-
-    /**
-     * Initializes static variables needed for Oracle-extensions and large BLOB/CLOB support.
-     */
-    protected void initOracleReflectedVars()
-    {
-        super.initOracleReflectedVars();
-        try
-        {
-            /*
-            Check for Oracle-specific classes, OracleConnection-specific
-            statement caching/row pre-fetch methods and Oracle BLOB/CLOB access methods.
-            We can do this in constructor in spite of possible mixing of instance being
-            able vs unable passed at runtime (since withouth these classes and methods
-            it's impossible to enable ORA-extensions at all even if instances are capable).
-            */
-            ORA_CONN_CLASS = ClassHelper.getClass("oracle.jdbc.OracleConnection", false);
-            ORA_PS_CLASS = ClassHelper.getClass("oracle.jdbc.OraclePreparedStatement", false);
-            ORA_CLOB_CLASS = ClassHelper.getClass("oracle.sql.CLOB", false);
-            ORA_BLOB_CLASS = ClassHelper.getClass("oracle.sql.BLOB", false);
-            PARAM_TYPE_INT_ORACLOB = new Class[]{ Integer.TYPE, ORA_CLOB_CLASS };
-            PARAM_TYPE_INT_ORABLOB = new Class[]{ Integer.TYPE, ORA_BLOB_CLASS };
-
-            /*
-            The unwrap pattern used in {@link org.apache.ojb.broker.util.UnwrapHelper}
-            to unwrap connection instance to Oracle's specific connection implementation
class.
-            */
-            Object[] oracleUnwrapPattern = new Object[] {"oracle 10g", UnwrapHelper.TYPE_METHOD,
-                    new Class[]{ORA_CONN_CLASS}, "unwrapCompletely", null, null, null};
-            unwrapHelper = new UnwrapHelper();
-            // add the oracle unwrap pattern
-            unwrapHelper.addUnwrapPattern(oracleUnwrapPattern);
-
-            METHOD_SET_STATEMENT_CACHE_SIZE =
-                    ClassHelper.getMethod(ORA_CONN_CLASS, "setStatementCacheSize", PARAM_TYPE_INTEGER);
-            METHOD_SET_IMPLICIT_CACHING_ENABLED =
-                    ClassHelper.getMethod(ORA_CONN_CLASS, "setImplicitCachingEnabled", PARAM_TYPE_BOOLEAN);
-            METHOD_SET_ROW_PREFETCH = ClassHelper.getMethod(ORA_CONN_CLASS, "setDefaultRowPrefetch",
PARAM_TYPE_INTEGER);
-            METHOD_SET_CLOB = ClassHelper.getMethod(ORA_PS_CLASS, "setCLOB", PARAM_TYPE_INT_ORACLOB);
-            METHOD_SET_BLOB = ClassHelper.getMethod(ORA_PS_CLASS, "setBLOB", PARAM_TYPE_INT_ORABLOB);
-
-            ORA_STATEMENT_CACHING_AVAILABLE =
-                    METHOD_SET_STATEMENT_CACHE_SIZE != null && METHOD_SET_IMPLICIT_CACHING_ENABLED
!= null;
-            ORA_ROW_PREFETCH_AVAILABLE = METHOD_SET_ROW_PREFETCH != null;
-            ORA_CLOB_HANDLING_AVAILABLE = METHOD_SET_CLOB != null;
-            ORA_BLOB_HANDLING_AVAILABLE = METHOD_SET_BLOB != null;
-        }
-        catch (ClassNotFoundException e)
-        {
-            // ignore (we tried...)
-        }
-        // Isolated checks for other connection classes (OK when not found)
-        try
-        {
-            JBOSS_CONN_CLASS = ClassHelper.getClass(JBOSS_CONN_NAME, false);
-        }
-        catch (ClassNotFoundException e)
-        {
-            // ignore (no problem)
-        }
-    }
-
 }

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracleImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracleImpl.java?view=diff&rev=489836&r1=489835&r2=489836
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracleImpl.java
(original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/platforms/PlatformOracleImpl.java
Fri Dec 22 18:40:42 2006
@@ -19,11 +19,16 @@
 import org.apache.ojb.broker.util.logging.LoggerFactory;
 import org.apache.ojb.broker.util.ClassHelper;
 import org.apache.ojb.broker.util.sequence.SequenceManagerHelper;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
+import org.apache.ojb.broker.PersistenceBrokerSQLException;
+import org.apache.commons.lang.SerializationUtils;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.StringReader;
+import java.io.Serializable;
 import java.lang.reflect.Field;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -34,6 +39,7 @@
 import java.sql.SQLException;
 import java.sql.Statement;
 import java.sql.Types;
+import java.sql.Blob;
 import java.util.Properties;
 
 /**
@@ -128,36 +134,55 @@
  * </tr>
  * </table>
  *
- * @author <a href="mailto:thma@apache.org">Thomas Mahler <a>
  * @version $Id$
  */
 
 public class PlatformOracleImpl extends PlatformDefaultImpl
 {
     protected static final String THIN_URL_PREFIX = "jdbc:oracle:thin";
-    // Oracle:thin handles direct BLOB insert <= 4000 and update <= 2000
-    protected static final int THIN_BLOB_MAX_SIZE = 2000;
-    // Oracle:thin handles direct CLOB insert and update <= 4000
-    protected static final int THIN_CLOB_MAX_SIZE = 4000;
 
     /**
      * Field value of <code>oracle.jdbc.OracleTypes.CURSOR</code>.
      * @see #initOracleReflectedVars
      */
-    protected static int ORACLE_JDBC_TYPE_CURSOR = -10;
+    protected int ORACLE_JDBC_TYPE_CURSOR = -10;
 
     private Logger logger = LoggerFactory.getLogger(PlatformOracleImpl.class);
 
+    public PlatformOracleImpl(JdbcConnectionDescriptor jcd)
+    {
+        super(jcd);
+        initOracleReflectedVars();
+    }
+
     /**
-     * Default constructor.
+     * Initializes static variables needed for getting Oracle-specific JDBC types.
      */
-    public PlatformOracleImpl()
+    private void initOracleReflectedVars()
     {
-        initOracleReflectedVars();
+        try
+        {
+            // Check for Oracle-specific Types class
+            final Class oracleTypes = ClassHelper.getClass("oracle.jdbc.OracleTypes", false);
+            final Field cursorField = oracleTypes.getField("CURSOR");
+            ORACLE_JDBC_TYPE_CURSOR = cursorField.getInt(null);
+        }
+        catch (ClassNotFoundException e)
+        {
+            log.warn("PlatformOracleImpl could not find Oracle JDBC classes");
+        }
+        catch (NoSuchFieldException e)
+        {
+            log.warn("PlatformOracleImpl could not find Oracle JDBC type fields");
+        }
+        catch (IllegalAccessException e)
+        {
+            log.warn("PlatformOracleImpl could not get Oracle JDBC type values");
+        }
     }
 
     /**
-     * Method prepareNextValProcedureStatement implementation 
+     * Method prepareNextValProcedureStatement implementation
      * is simply copied over from PlatformMsSQLServerImpl class.
      * @see org.apache.ojb.broker.platforms.Platform#prepareNextValProcedureStatement(java.sql.Connection,
java.lang.String, java.lang.String)
      */
@@ -198,25 +223,22 @@
      * all cases it's better to use setBinaryStream. Oracle also requires a change in the
resultset
      * type of the prepared statement. MBAIRD NOTE: BLOBS may not work with Oracle database/thin
      * driver versions prior to 8.1.6.
-     * 
+     *
      * @see Platform#setObjectForStatement
      */
     public void setObjectForStatement(PreparedStatement ps, int index, Object value, int
sqlType)
             throws SQLException
     {
-        if (((sqlType == Types.VARBINARY) || (sqlType == Types.LONGVARBINARY) || (sqlType
== Types.BLOB))
-                && (value instanceof byte[]))
+        if ((sqlType == Types.VARCHAR || sqlType == Types.CHAR) && (value instanceof
String || value instanceof Character))
         {
-            byte buf[] = (byte[]) value;
-            int length = buf.length;
-            if (isUsingOracleThinDriver(ps.getConnection()) && length > THIN_BLOB_MAX_SIZE)
-            {
-                throw new SQLException(
-                        "Oracle thin driver cannot update BLOB values with length>2000.
(Consider using Oracle9i as OJB platform.)");
-            }
-            ByteArrayInputStream inputStream = new ByteArrayInputStream(buf);
-            changePreparedStatementResultSetType(ps);
-            ps.setBinaryStream(index, inputStream, length);
+            if (value instanceof String)
+            {
+                ps.setString(index, (String) value);
+            }
+            else // assert: value instanceof Character
+            {
+                ps.setString(index, value.toString());
+            }
         }
         else if (value instanceof Double)
         {
@@ -254,29 +276,55 @@
                 reader = new InputStreamReader(inputStream);
                 length = buf.length;
             }
-            if (isUsingOracleThinDriver(ps.getConnection()) && length > THIN_CLOB_MAX_SIZE)
-            {
-                throw new SQLException(
-                        "Oracle thin driver cannot insert CLOB values with length>4000.
(Consider using Oracle9i as OJB platform.)");
-            }
             ps.setCharacterStream(index, reader, length);
         }
-        else if ((sqlType == Types.CHAR || sqlType == Types.VARCHAR)
-                 &&
-                 (value instanceof String || value instanceof Character))
+        else if ((value instanceof byte[]) && ((sqlType == Types.VARBINARY) || (sqlType
== Types.LONGVARBINARY) || (sqlType == Types.BLOB)))
         {
-            if (value instanceof String)
+//            byte buf[] = (byte[]) value;
+//            int length = buf.length;
+//            ByteArrayInputStream inputStream = new ByteArrayInputStream(buf);
+//            // arminw: seems this no longer mandatory
+//            //changePreparedStatementResultSetType(ps);
+//            ps.setBinaryStream(index, inputStream, length);
+            ps.setBytes(index, (byte[]) value);
+        }
+        else if(sqlType == Types.JAVA_OBJECT)
+        {
+            // JAVA_OBJECT is not proper supported, workaround: use BLOB type
+            byte[] ser = SerializationUtils.serialize((Serializable) value);
+            ps.setBytes(index, ser);
+        }
+        else
+        {
+            super.setObjectForStatement(ps, index, value, sqlType);
+        }
+    }
+
+    public Object postPrepareReadInValue(final FieldDescriptor fld, final Object value)
+    {
+        /*
+        workaround for JAVA_OBJECT type. Currently Oracle doesn't
+        proper support JAVA_OBJECT type. On insert we transform JAVA_OBJECT
+        to byte[] array, thus on read we have to deserialize. The mapping type
+        is BLOB.
+        */
+        if(fld.getJdbcType().getType() == Types.JAVA_OBJECT && value instanceof Blob)
+        {
+            Blob ret = (Blob) value;
+            byte[] b;
+            try
             {
-                ps.setString(index, (String) value);
+                b = ret.getBytes(1, (int) ret.length());
             }
-            else // assert: value instanceof Character
+            catch(SQLException e)
             {
-                ps.setString(index, value.toString());
+                throw new PersistenceBrokerSQLException("Can't read Blob object of serialized
JAVA_OBJECT type", e);
             }
+            return SerializationUtils.deserialize(b);
         }
         else
         {
-            super.setObjectForStatement(ps, index, value, sqlType);
+            return super.postPrepareReadInValue(fld, value);
         }
     }
 
@@ -314,6 +362,11 @@
         return ORACLE_JOIN_SYNTAX;
     }
 
+    public boolean supportsOrderByInSubSelect()
+    {
+        return false;
+    }
+
     public String createSequenceQuery(String sequenceName)
     {
         return "CREATE SEQUENCE " + sequenceName;
@@ -399,15 +452,14 @@
     /**
      * @see org.apache.ojb.broker.platforms.Platform#registerOutResultSet(java.sql.CallableStatement,
int)
      */
-    public void registerOutResultSet(CallableStatement stmt, int position)
-            throws SQLException
+    public void registerOutResultSet(CallableStatement stmt, int position) throws SQLException
     {
         stmt.registerOutParameter(position, ORACLE_JDBC_TYPE_CURSOR);
     }
 
     /**
      * Checks if the supplied connection is using the Oracle thin driver.
-     * 
+     *
      * @param conn database connection for which to check JDBC-driver
      * @return <code>true</code> if the connection is using Oracle thin driver,
<code>false</code>
      *         otherwise.
@@ -435,31 +487,4 @@
         }
         return false;
     }
-
-    /**
-     * Initializes static variables needed for getting Oracle-specific JDBC types.
-     */
-    protected void initOracleReflectedVars()
-    {
-        try
-        {
-            // Check for Oracle-specific Types class
-            final Class oracleTypes = ClassHelper.getClass("oracle.jdbc.OracleTypes", false);
-            final Field cursorField = oracleTypes.getField("CURSOR");
-            ORACLE_JDBC_TYPE_CURSOR = cursorField.getInt(null);
-        }
-        catch (ClassNotFoundException e)
-        {
-            log.warn("PlatformOracleImpl could not find Oracle JDBC classes");
-        }
-        catch (NoSuchFieldException e)
-        {
-            log.warn("PlatformOracleImpl could not find Oracle JDBC type fields");
-        }
-        catch (IllegalAccessException e)
-        {
-            log.warn("PlatformOracleImpl could not get Oracle JDBC type values");
-        }
-    }
-
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message