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
相关产品推荐
相关产品推荐

