You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

sqljdbc4与mssql-jdbc中Statement.execute()行为差异及问题咨询

JDBC驱动切换后存储过程结果集获取异常问题

问题背景

我们的Java代码使用Statement执行SQL的逻辑如下:

Statement stmt = _CONN.createStatement();
boolean isRst = stmt.execute(sql);
if (isRst) {
    do {
        ResultSet rs = stmt.getResultSet();
        setColumnInfo(rs);
        while (rs.next())
            outputOneRecord(rs);
        rs.close();
    } while (fullerror && stmt.getMoreResults());
} else {
    int r = stmt.getUpdateCount();
    if (r != -1)
        logger.info("Update count: {}", r);
}

该逻辑已稳定运行多年。近期将JDBC驱动依赖从旧版本:

<dependency>
    <groupId>com.microsoft</groupId>
    <artifactId>sqljdbc4</artifactId>
    <version>4.0.2206.100</version>
</dependency>

切换为新版本:

<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>12.4.1.jre11</version>
</dependency>

切换后,多数功能正常,但一个先执行更新操作、最终以SELECT语句结尾的存储过程出现异常:旧驱动会返回SELECT语句的结果,新驱动下stmt.execute(sql)返回false,代码仅上报更新计数后退出,未输出任何行数据。仅切换回旧驱动即可恢复正常。

问题解答

这是已文档化的行为变更,并非新驱动的Bug。

原因说明

旧的sqljdbc4驱动行为不符合JDBC规范:JDBC规范明确规定,Statement.execute()方法的返回值表示第一个结果的类型——如果第一个结果是ResultSet则返回true,如果是更新计数则返回false。但旧驱动在处理多结果语句(如包含更新+查询的存储过程)时,错误地将最后一个结果的类型作为返回值,导致即使第一个结果是更新操作,也会返回true。

新的mssql-jdbc驱动修正了这个问题,严格遵循JDBC规范,返回第一个结果的类型。因此当存储过程第一个操作是更新时,execute()返回false,原代码仅处理一次更新计数就退出,漏掉了后续的SELECT结果集。

解决方案

修改代码逻辑,不再依赖execute()的初始返回值,而是循环遍历所有结果,直到没有更多结果为止。正确的处理逻辑示例:

Statement stmt = _CONN.createStatement();
boolean hasResults = stmt.execute(sql);
do {
    if (hasResults) {
        // 处理结果集
        ResultSet rs = stmt.getResultSet();
        setColumnInfo(rs);
        while (rs.next())
            outputOneRecord(rs);
        rs.close();
    } else {
        // 处理更新计数
        int updateCount = stmt.getUpdateCount();
        if (updateCount != -1) {
            logger.info("Update count: {}", updateCount);
        }
    }
    // 切换到下一个结果
    hasResults = stmt.getMoreResults();
} while (hasResults || stmt.getUpdateCount() != -1);
stmt.close();

这段代码会依次处理所有的更新计数和结果集,无论它们出现的顺序如何,完全符合JDBC规范,能兼容新旧驱动。

内容的提问来源于stack exchange,提问作者Mikhail T.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 15:07:26