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

Eclipse中‘Run on server’执行SQL无法更新数据库问题求助

Servlet连接数据库无法更新数据的问题排查与修复

问题描述

我正在尝试让Servlet程序连接数据库并执行操作。在Eclipse中,把连接和查询代码放到main()方法里,选择“Run as java application”运行时,能正常更新数据库;但通过“Run on server”启动HTML,把查询代码放到doGet()方法时,Servlet运行正常,浏览器里的HTML内容也能更新,却无法更新数据库。我也试过把代码放在main()方法里,再通过doGet()调用,同样没用。

相关代码

HTML页面

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Register</title>
</head>
<body>
    <form action="register" method="get">
        <label for="uname">Username:</label>
        <input type="text" name="uname">
        <label for="pwd">Password:</label>
        <input type="text" name="pwd">
        <button type="submit">Register</button>
    </form>
</body>
</html>

Servlet的doGet()方法

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
    // response.getWriter().append("Served at: ").append(request.getContextPath());
    PrintWriter pw = response.getWriter();
    String uname = request.getParameter("uname");
    String pwd = request.getParameter("pwd");
    Connection con = null;
    try {
        Class.forName("com.mysql.cj.jdbc.Driver");
        con = DriverManager.getConnection("jdbc:mysql://localhost:3306/advjavada", "root", "");
        if(!con.isClosed()) {
            System.out.println("Connection SUCCESSFUL!");
            PreparedStatement ps = con.prepareStatement("insert into userdata(uname, pwd) value('sample2', 'sampass2');");
            //ResultSet rs = ps.executeQuery();
            ps.executeQuery();
        }
        else {
            System.out.println("Connection FAILED!");
        }
    }
    catch (Exception e) {
        System.err.print(e.getMessage());
    }
    pw.println("<h1>Hello, " + uname + "!</h1><p>Registration Successful</p>");
    pw.close();
}

问题根源及修复方案

1. 执行插入操作的方法错误

你用ps.executeQuery()执行INSERT语句,这个方法仅适用于查询语句(返回ResultSet结果集)。执行INSERT/UPDATE/DELETE这类修改数据的语句,必须用ps.executeUpdate(),它会返回受影响的行数,能直接确认操作是否生效。

2. 事务处理缺失

JDBC默认开启自动提交,但部分场景下可能因数据库配置或驱动特性导致提交失效。建议显式控制事务,异常时回滚,保证数据一致性:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    PrintWriter pw = response.getWriter();
    String uname = request.getParameter("uname");
    String pwd = request.getParameter("pwd");
    Connection con = null;
    PreparedStatement ps = null;
    try {
        Class.forName("com.mysql.cj.jdbc.Driver");
        con = DriverManager.getConnection("jdbc:mysql://localhost:3306/advjavada", "root", "");
        con.setAutoCommit(false); // 关闭自动提交,手动控制事务
        
        if(!con.isClosed()) {
            System.out.println("Connection SUCCESSFUL!");
            // 使用用户提交的参数,替换硬编码内容,同时避免SQL注入
            ps = con.prepareStatement("insert into userdata(uname, pwd) values(?, ?)");
            ps.setString(1, uname);
            ps.setString(2, pwd);
            
            int affectedRows = ps.executeUpdate();
            System.out.println("受影响行数:" + affectedRows);
            con.commit(); // 提交事务
        } else {
            System.out.println("Connection FAILED!");
        }
        pw.println("<h1>Hello, " + uname + "!</h1><p>Registration Successful</p>");
    } catch (Exception e) {
        // 异常时回滚事务
        if(con != null) {
            try {
                con.rollback();
            } catch(SQLException ex) {
                ex.printStackTrace();
            }
        }
        e.printStackTrace(); // 打印完整异常栈,方便排查问题
        pw.println("<h1>Registration Failed</h1><p>" + e.getMessage() + "</p>");
    } finally {
        // 关闭资源,避免连接泄漏
        try {
            if(ps != null) ps.close();
            if(con != null) con.close();
        } catch(SQLException e) {
            e.printStackTrace();
        }
        pw.close();
    }
}

3. 资源泄漏问题

原代码未关闭PreparedStatement和Connection,长期运行会导致数据库连接耗尽。可以用finally块手动关闭,或使用Java 7+的try-with-resources语法自动关闭:

try (Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/advjavada", "root", "");
     PreparedStatement ps = con.prepareStatement("insert into userdata(uname, pwd) values(?, ?)")) {
    con.setAutoCommit(false);
    ps.setString(1, uname);
    ps.setString(2, pwd);
    int affectedRows = ps.executeUpdate();
    con.commit();
} catch (Exception e) {
    // 异常处理
}

4. 硬编码数据问题

原代码插入固定值而非用户提交的uname和pwd,改用预编译语句的参数化方式,既实现业务需求,又能避免SQL注入风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 04:24:32