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

