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:[EMAIL PROTECTED]">Matthew Baird</a>
- * @author <a href="mailto:[EMAIL PROTECTED]">Martin Kalé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 [EMAIL PROTECTED]
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 [EMAIL PROTECTED]
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 [EMAIL PROTECTED]
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:[EMAIL PROTECTED]">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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]