[
http://opensource.atlassian.com/projects/hibernate/browse/HHH-3360?page=c...
]
Manuel Dominguez Sarmiento commented on HHH-3360:
-------------------------------------------------
Hi Fabian,
I can vouch for this patch, it has been reliably working in our production servers for
over a year without problems. I think what's going on is that having JBoss wrappers in
the middle is bringing trouble into the equation. Please refer to the following link (see
the second section, "Example of Oracle Update Batching"):
http://www.oracle.com/technology/products/oracle9i/daily/jun07.html
Explicit flushes are not required, except for the final flush which is performed in
doExecuteBatch() - the reason is that the Oracle batching model automatically flushes
pending operations on invocations to ps.executeUpdate(). This statement returns 0 while
the queue is not full, but when the batch size is reached, pending operations are
automatically flushed, and the returned value is then the total number of updated rows
(combined value for all DML statements in the flushed batch).
For this to work correctly, setExecuteBatch(int batchSize) must be invoked on the
corresponding OraclePreparedStatement before the batch begins. This is where it gets
tricky. Simply casting the PreparesStatement provided by Hibernate will only work if you
are working directly with the Oracle JDBC driver. In our case we use C3P0 connection
pooling which wraps Connections and PreparedStatements, but still provides a way to access
the underlying "native" OraclePreparedStatement.
This is why we have setExecuteBatch() as a protected template method which can be
overridden by subclasses. C3P0OracleBatchingBatcher overrides this method (as well as
sendBatch) in order to access the native Oracle classes. C3P0 requires doing this using
reflection, so it's not pretty, but it works.
My guess is that you need to figure out how JBoss is wrapping the PreparedStatements so
that you can mirror what C3P0OracleBatchingBatcher is doing, but applying the same concept
to JBoss.
Hope this helps,
- Manuel
Custom Oracle Batcher to allow batch updates for versioned data
---------------------------------------------------------------
Key: HHH-3360
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-3360
Project: Hibernate Core
Issue Type: Improvement
Components: core
Affects Versions: 3.2.0.ga, 3.2.1, 3.2.2, 3.2.3, 3.2.4, 3.2.4.sp1, 3.2.5, 3.2.6,
3.3.0.CR1
Environment: Oracle 10g R1, 10g R2, 11g R1 (have not tried previous Oracle
versions), 11g R1 drivers (older drivers should also work)
Reporter: Manuel Dominguez Sarmiento
Priority: Minor
Attachments: C3P0OracleBatchingBatcher.java,
C3P0OracleBatchingBatcherFactory.java, OracleBatchingBatcher.java,
OracleBatchingBatcher.java, OracleBatchingBatcherFactory.java
Original Estimate: 30 minutes
Remaining Estimate: 30 minutes
We have developed a custom Oracle Batcher which allows batching versioned data. The
Oracle JDBC driver does not return update counts when using the standard JDBC 2.0 batching
mechanism, however the proprietary Oracle batching mechanism allows obtaining the total
batch row update count. The update counts are absolutely necessary to detect stale
updates.
Although it is not exactly the same, the total row update count is actually enough
information to be able to batch versioned data and still detect stale updates.
We'd like to contribute the attached files. They have a compile time dependency on
Oracle JDBC. If this is not acceptable, it could be easily solved by using reflection.
Another Batcher is provided for when the Oracle connection is being managed through c3p0
(a common deployment scenario). This has a compile time dependency on c3p0.
A few "dirty" tricks were necessary to pull this off without patching other
classes. Specifically, it was necessary to override Java private semantics to obtain
BasicExpectation.expectedRowCount. This could be easily solved by adding an accessor
method to the Expectation interface.
There is one issue which we are not completely sure of, however so far we have not found
any problems. When the Expectation is NONE, there is no way to check whether the total row
count is correct or not, even if other batched updates do have expectations with expected
row counts. Our understanding is that actually, since batching requires all statements to
be of the same type (since the same PreparedStatement / CallableStatement is being used),
then either ALL expectations will be NONE, or all will have an expected row count.
We'd welcome comments from the Hibernate team. This could also be probably handled
better by improving the Expectation interface.
Oracle JDBC docs that explain the Oracle batching model:
http://download.oracle.com/docs/cd/B28359_01/java.111/b31224/oraperf.htm#...
As expected, implementing this solution has resulted in drastical improvement in batch
processing.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira