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

Java SQLException:参数15未赋值问题排查(附代码)

排查 java.sql.SQLException: No value specified for parameter 15 错误

首先,我一眼就看到了代码里的致命问题——你在循环内部重新赋值了preparedStmt变量,把原本用于UPDATE的PreparedStatement替换成了SELECT的,这直接导致后续设置参数15的时候,操作的根本不是原来的UPDATE语句的PreparedStatement!

问题详细分析

你原本初始化的preparedStmt是对应UPDATE语句的(包含16个占位符),但在这段分支代码里:

String strSelectQuery = "SELECT * FROM `cve_data` where `CVE_ID` ='" +strCVEID+ "' ";
preparedStmt = null;
preparedStmt = con.prepareStatement(strSelectQuery); // 这里替换了原来的UPDATE stmt!
ResultSet rs = preparedStmt.executeQuery();

当进入这个分支后,preparedStmt已经变成了对应SELECT语句的对象,而这个SELECT语句没有任何占位符。之后你再调用preparedStmt.setString(15, flag)或者preparedStmt.setString(15, "1"),本质上是在操作SELECT的PreparedStatement,它根本不需要参数,自然会报错说参数15未指定。

更糟的是,你之后继续调用preparedStmt.setString(16, ...)和preparedStmt.execute(),这时候执行的已经不是UPDATE而是SELECT了,完全偏离了你的预期。

修复方案

解决方法很简单:不要复用同一个preparedStmt变量,给SELECT操作单独创建一个新的PreparedStatement对象,避免覆盖原来的UPDATE语句的对象。

修改后的核心代码片段如下:

// 3 condition code starts here
String str = (String)hmCVEInsData.get("CVECVSSscore");
if(str.equals("")){
    str = "0.0";
}
String flag = "0";
double fNum = Double.parseDouble(str);
if ( fNum >= CVSS_2_Critical_Base || fNum >= CVSS_3_Critical_Base){
    String strCVEID = (String)hmCVEInsData.get("CVEName");
    System.out.println(strCVEID);
    // 用新变量创建SELECT的PreparedStatement,不覆盖原UPDATE的stmt
    String strSelectQuery = "SELECT * FROM `cve_data` where `CVE_ID` = ? "; 
    // 改用占位符避免SQL注入风险
    PreparedStatement selectStmt = con.prepareStatement(strSelectQuery);
    selectStmt.setString(1, strCVEID);
    ResultSet rs = selectStmt.executeQuery();
    while ( rs.next() ) {
        String srtrCVSSSCORE = rs.getString("CVSS_SCORE");
        System.out.println(srtrCVSSSCORE);
        String strTISeverity = rs.getString("CVE_TI_SEVERITY");
        System.out.println(strTISeverity);
        double fNum2 = Double.parseDouble(srtrCVSSSCORE);
        if ( fNum2 >= fNum ){
            System.out.println("Inside the loop");
            // 操作原UPDATE的preparedStmt
            preparedStmt.setString (15, flag);
        } else {
            System.out.println("Inside the Else");
            preparedStmt.setString (15, "1");
        }
    }
    // 及时关闭资源,避免泄漏
    rs.close();
    selectStmt.close();
}
// 3 condition code ends here
// 继续操作正确的UPDATE preparedStmt
preparedStmt.setString (16, (String)hmCVEInsData.get("CVEName"));
preparedStmt.execute();

额外优化建议

  • 防范SQL注入:原SELECT语句用字符串拼接参数,存在注入风险,改成占位符方式更安全,就像上面代码里那样。
  • 默认值兜底:可以在条件分支外先给参数15设置默认值(比如preparedStmt.setString(15, "0")),确保即使不进入条件分支,也不会出现参数未赋值的情况。
  • 资源自动释放:建议使用try-with-resources语法,让JVM自动关闭ResultSet、PreparedStatement等资源,避免手动关闭遗漏导致的连接泄漏。

内容的提问来源于stack exchange,提问作者user9265682

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:59:59