使用JSP+JDBC+Servlet开发登录表单遇参数索引越界错误求助
解决JDBC PreparedStatement参数索引越界问题(SQLState: S1009)
你的错误Parameter index out of range (1 > number of parameters, which is 0)是因为SQL语句里把PreparedStatement的占位符?用单引号括起来了。JDBC会将单引号内的内容视为普通字符串,而不是可绑定的参数占位符,导致这条SQL实际没有需要绑定的参数,但你后续调用setString(1, ...)和setString(2, ...)时,就会触发参数索引越界错误。
修正步骤:
直接移除SQL语句中?两侧的单引号即可,修正后的SQL应该是:
SELECT * from myshop.userlogin WHERE username = ? and password = ?
修正后的完整LoginDao代码:
public class LoginDao { public boolean validate(LoginBean loginBean) throws ClassNotFoundException { boolean status = false; Class.forName("com.mysql.cj.jdbc.Driver"); try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/myshop?user=root", "root", "12301230"); PreparedStatement preparedStatement = connection.prepareStatement("SELECT * from myshop.userlogin WHERE username = ? and password = ?")) { preparedStatement.setString(1, loginBean.getUsername()); preparedStatement.setString(2, loginBean.getPassword()); System.out.println(preparedStatement); ResultSet rs = preparedStatement.executeQuery(); status = rs.next(); } catch (SQLException e) { printSQLException(e); } return status; } private void printSQLException(SQLException ex) { for (Throwable e: ex) { if (e instanceof SQLException) { e.printStackTrace(System.err); System.err.println("SQLState: " + ((SQLException) e).getSQLState()); System.err.println("Error Code: " + ((SQLException) e).getErrorCode()); System.err.println("Message: " + e.getMessage()); Throwable t = ex.getCause(); while (t != null) { System.out.println("Cause: " + t); t = t.getCause(); } } } } }
额外注意事项:
- PreparedStatement的占位符
?不需要加任何引号,JDBC会根据参数类型自动处理转义和引号包裹,同时还能避免SQL注入风险。 - 你的数据库连接URL中已经包含了
user=root,后续getConnection又传入了用户名参数,虽然不影响功能,但建议统一写法(要么URL里携带,要么通过方法参数传递)。 - 生产环境绝对不能明文存储用户密码,建议使用BCrypt、Argon2等哈希算法对密码加密后再存入数据库。
内容的提问来源于stack exchange,提问作者Ronniel
相关产品推荐
相关产品推荐

