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

求助:JSP中出现ServletException及ResultSet起始前SQLException异常

问题排查与解决方案

异常原因

你遇到的java.sql.SQLException: Before start of result set异常,核心原因是复用了同一个Statement对象执行两次查询。JDBC规范明确规定:当使用同一个Statement执行新的查询时,之前关联的ResultSet会被自动关闭。你的代码中,在遍历rs1的过程中,用同一个stmt执行了第二次查询,导致rs1提前失效,后续再尝试操作rs1就会触发该异常。

另外原代码还存在几个潜在问题:

  • 直接拼接SQL字符串,存在严重的SQL注入风险
  • 未正确关闭数据库资源(Connection、Statement、ResultSet),会导致连接泄漏
  • HTML结构不严谨:如果查询无结果,</select></p>会无对应开头标签

修复方案

1. 为每次查询创建独立的Statement/PreparedStatement

不要复用同一个Statement对象,每次查询都使用新的对象,推荐使用PreparedStatement(参数化查询)替代Statement,既解决ResultSet冲突问题,又避免SQL注入。

2. 使用try-with-resources自动管理资源

Java 7及以上支持try-with-resources语法,可自动关闭实现AutoCloseable接口的资源(如Connection、PreparedStatement、ResultSet),无需手动调用close(),避免资源泄漏。

3. 增加空值与无结果判断

避免因username为空或查询无结果导致的逻辑错误与HTML结构问题。

修改后的完整代码

<%
// 加载驱动(MySQL 5.x需要,MySQL 8.x可省略,驱动类已改为com.mysql.cj.jdbc.Driver)
Class.forName("com.mysql.jdbc.Driver");

// try-with-resources自动关闭资源
try (Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql", "root", "12345");
     // 第一个查询:根据用户名获取部门
     PreparedStatement deptStmt = con.prepareStatement("select EDepartment from empinfo where EUsername=?")) {

    String username = (String) session.getAttribute("username");
    if (username != null) {
        deptStmt.setString(1, username);
        try (ResultSet deptRs = deptStmt.executeQuery()) {
            if (deptRs.next()) {
                String department = deptRs.getString("EDepartment");
                // 第二个查询:根据部门获取所有用户名,使用独立的PreparedStatement
                try (PreparedStatement userStmt = con.prepareStatement("select EUsername from empinfo where EDepartment=?")) {
                    userStmt.setString(1, department);
                    try (ResultSet userRs = userStmt.executeQuery()) {
%>
<select>
<%
                        while (userRs.next()) {
%>
    <option><%= userRs.getString("EUsername") %></option>
<%
                        }
%>
</select>
<%
                    }
                }
            } else {
%>
<p>未找到当前用户的部门信息</p>
<%
            }
        }
    } else {
%>
<p>请先登录</p>
<%
    }
} catch (ClassNotFoundException | SQLException e) {
    // 实际项目中请使用日志框架记录异常,不要直接打印
    e.printStackTrace();
}
%>

关键修改点说明

  • 拆分两次查询为独立的PreparedStatement,避免ResultSet被提前关闭
  • 使用参数化查询(?占位符)替代字符串拼接,彻底杜绝SQL注入
  • 增加username非空判断、查询结果存在性判断,处理边界情况
  • 用try-with-resources自动管理数据库资源,避免连接泄漏
  • 调整HTML结构,确保只有查询有结果时才输出<select>标签,避免无效标签

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:24:33