问题
How to use optimistic locking with batch updates? I am using SimpleJdbcTemplate
and for a single row I can build update sql that increments version column value and includes version in WHERE clause.
Unfortunately the result int[] updated = simpleJdbcTemplate.batchUpdate
does not contain rowcounts when using oracle driver. All elements are -2 indicating unknown rowcount.
Is there some other, more performant way of doing this than executing all updates individually? These batches contain an average of 5 items (only) but may be up to 250.
回答1:
Just thinking aloud here - if it's a problem with the batch support in the driver, you could try to achieve the same using a single query, making batching less relevant. (As you know, batching is about avoiding latency with multiple queries, but latency is still present even when batching a single query.)
Here's how you might achieve the optimistic update with a single query
- Build a temporary table that contains the conditions necessary for a row update, and rewrite your update query to be a join on this table. (e.g. outer join the current timestamp in the live data with the timestamp in your temporary table.) If the timestamp on the live data has not been updated then the row will be selected from your temporary table.
Since you can use the temporary table as a select query, you can find which rows would be updated, and then submit this as an update query. (All within a transaction, of course.)
To illustrate:
TempUpdateTable
---------------
id, // id of the row to be updated
timestamp, // timestamp data originally fetched
data1 // data to be updated
data2
dataN
This gives the ids of all data to be updated, which you can store for later reference
SELECT d.id FROM TempUpdateTable t JOIN YourData d
ON t.id=d.id WHERE t.timestamp=d.timestamp
The same query can then be used in an update statement
UPDATE YourData
SET data=t.data1
SET data=t.data2 //etc...
FROM TempUpdateTable t WHERE t.id IN
(SELECT d.in FROM TempUpdateTable t JOIN YourData d
ON t.id=d.id WHERE d.timestamp=d.timestamp)
回答2:
When I was working for Hibernate, we noticed that the older Oracle JDBC Driver versions did not report the update count correctly, and that's why Hibernate used to disable batch updates for entities using optimistic locking.
However, since Hibernate 5, this is no longer the default strategy as JDBC drivers handle the batch update count better.
So, in your case, you need to update the Oracle JDBC Driver to at least 12c. Note that the Oracle JDBC Driver is both backward and forward compatible, so you can use it even with Oracle 11g on the database server-side.
Since September 2019, you can even get the Oracle JDBC Driver from Maven Central:
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version>
</dependency>
I'm using version 19 of the driver with Oracle 18 XE, and it works like a charm even when mixing batch updates with optimistic locking.
来源:https://stackoverflow.com/questions/2910715/optimistic-locking-batch-update