乐观锁定批量更新

时间:2010-05-26 06:59:13

标签: java jdbc batch-file optimistic-locking

如何使用批量更新的乐观锁定?我正在使用SimpleJdbcTemplate,对于单行,我可以构建更新sql,它增加版本列值并包含WHERE子句中的版本。

不幸的是,使用oracle驱动程序时,结果int[] updated = simpleJdbcTemplate.batchUpdate不包含行计数。所有元素都是-2表示未知的行数。

除了单独执行所有更新之外,还有其他更高效的方法吗?这些批次平均包含5个项目(仅限),但可能最多250个。

2 个答案:

答案 0 :(得分:2)

在这里大声思考 - 如果驱动程序中的批处理支持存在问题,您可以尝试使用单个查询实现相同的功能,从而降低批处理的相关性。 (如您所知,批处理是关于避免多个查询的延迟,但即使批处理单个查询,延迟仍然存在。)

以下是使用单个查询实现乐观更新的方法

  • 构建一个临时表,其中包含行更新所需的条件,并将更新查询重写为此表上的联接。 (例如,外部连接实时数据中的当前时间戳和临时表中的时间戳。)如果实时数据的时间戳尚未更新,则将从临时表中选择该行。

由于您可以将临时表用作选择查询,因此可以查找要更新的行,然后将其作为更新查询提交。 (当然,所有这些都在交易中。)

举例说明:

TempUpdateTable
---------------
id,        // id of the row to be updated
timestamp, // timestamp data originally fetched
data1      // data to be updated
data2
dataN

这样可以更新所有数据的ID,您可以存储这些数据供以后参考

SELECT d.id FROM TempUpdateTable t JOIN YourData d 
    ON t.id=d.id WHERE t.timestamp=d.timestamp

然后可以在更新语句中使用相同的查询

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)

答案 1 :(得分:0)

当我为Hibernate工作时,我们注意到较早的Oracle JDBC驱动程序版本未正确报告更新计数,这就是Hibernate过去使用乐观锁定为实体禁用批量更新的原因。

但是,从Hibernate 5开始,这不再是默认策略,因为JDBC驱动程序可以更好地处理批处理更新计数。

因此,在您的情况下,您需要将Oracle JDBC驱动程序更新为至少12c。请注意,Oracle JDBC驱动程序是向后和向前兼容的,因此即使在数据库服务器端的Oracle 11g中,您也可以使用它。

自2019年9月起,您甚至可以从Maven Central获取Oracle JDBC驱动程序:

<dependency>
    <groupId>com.oracle.ojdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>19.3.0.0</version>
</dependency>

我将驱动程序的版本19与Oracle 18 XE一起使用,即使将批处理更新与乐观锁定混合使用,它也可以像魅力一样发挥作用。