批量更新时getUpdateCount在不同数据库返回结果为何不一致?
我在执行批量更新操作时,尝试获取受影响的总行数。使用getUpdateCount()方法在Oracle数据库中能得到正确结果,但在PostgreSQL、SQL Server和H2数据库中,这个API无法返回正确值,必须遍历executeBatch()的输出结果累加才能得到总数。
代码示例
PreparedStatement preparedStatement = connection.prepareStatement(getSQL()); // 通过addBatch()创建批量查询 int[] ints = preparedStatement.executeBatch(); connection.commit(); int updateCount = preparedStatement.getUpdateCount(); Assert.assertEquals(updateCount,3); Assert.assertNotNull(ints);
使用的数据库驱动依赖
<dependency> <groupId>com.oracle.ojdbc</groupId> <artifactId>ojdbc8</artifactId> <version>19.3.0.0</version> <scope>test</scope> </dependency> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> <version>12.2.0.jre8</version> <scope>test</scope> </dependency> <dependency> <groupId>net.sourceforge.jtds</groupId> <artifactId>jtds</artifactId> <version>1.3.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.6.0</version> <scope>test</scope> </dependency>
差异原因分析
这是JDBC规范的模糊性结合不同数据库驱动实现差异导致的:
JDBC规范的定义边界:JDBC规范中,
getUpdateCount()的核心用途是获取单个SQL语句执行后的受影响行数。对于批量操作,规范明确将批量结果的返回载体定为executeBatch()输出的int[]数组——数组中每个元素对应批量里单条语句的受影响行数,或是Statement.SUCCESS_NO_INFO(执行成功但无行数信息)、Statement.EXECUTE_FAILED(执行失败)这类状态标记,并未强制要求getUpdateCount()返回批量的总行数总和。Oracle驱动的扩展实现:Oracle的ojdbc驱动额外做了扩展,让
getUpdateCount()在批量执行完成后返回所有语句的受影响行数总和,这属于驱动厂商的自定义行为,并非JDBC规范的强制要求。其他数据库驱动的规范实现:PostgreSQL、SQL Server(包括jtds驱动)、H2的驱动严格遵循JDBC规范,批量执行后
getUpdateCount()要么返回-1(表示无更多结果),要么仅返回最后一条语句的受影响行数,不会自动累加批量的总数。因此必须手动遍历executeBatch()返回的数组,累加其中的有效数值来得到总受影响行数。
内容的提问来源于stack exchange,提问作者Piyush Bali

