Java操作SQLite:数据存在性校验与更新方法及密码修改功能无响应问题排查求助
嗨,我来帮你梳理这两个问题——先讲清楚Java操作SQLite的标准流程,再帮你排查密码修改按钮的bug。
要完成「读取数据→校验是否存在→匹配时更新」的流程,核心是用PreparedStatement(避免SQL注入,也更安全),步骤如下:
引入SQLite驱动
首先确保项目里包含sqlite-jdbc依赖,比如Maven项目可以在pom.xml中添加:<dependency> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.45.2.0</version> </dependency>建立数据库连接
使用DriverManager获取SQLite连接,URL格式为jdbc:sqlite:你的数据库文件路径:Connection conn = null; try { Class.forName("org.sqlite.JDBC"); conn = DriverManager.getConnection("jdbc:sqlite:user_db.db"); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "数据库连接失败:" + e.getMessage()); }读取数据并校验存在性
用预编译SQL查询目标数据,校验密码是否匹配,匹配则执行更新:String username = "test_user"; String oldPassword = "old_pass"; String newPassword = "new_pass"; // 使用参数占位符?,避免字符串拼接的SQL注入风险 String checkSql = "SELECT password FROM Login WHERE username = ?"; String updateSql = "UPDATE Login SET password = ? WHERE username = ?"; try (PreparedStatement checkStmt = conn.prepareStatement(checkSql)) { // 设置查询参数(索引从1开始) checkStmt.setString(1, username); ResultSet rs = checkStmt.executeQuery(); if (rs.next()) { // 校验原密码是否匹配 String storedPassword = rs.getString("password"); if (storedPassword.equals(oldPassword)) { // 密码匹配,执行更新操作 try (PreparedStatement updateStmt = conn.prepareStatement(updateSql)) { updateStmt.setString(1, newPassword); updateStmt.setString(2, username); int affectedRows = updateStmt.executeUpdate(); if (affectedRows > 0) { JOptionPane.showMessageDialog(null, "密码修改成功!"); } } } else { JOptionPane.showMessageDialog(null, "原密码错误!", "提示", JOptionPane.ERROR_MESSAGE); } } else { JOptionPane.showMessageDialog(null, "该用户不存在!"); } } catch (SQLException e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "数据库操作出错:" + e.getMessage()); } finally { // 关闭数据库连接 if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
看了你给出的按钮事件代码,几个关键问题导致点击后无反应:
空catch块吃掉所有异常:你的代码里
catch (Exception e) {}没有任何处理,哪怕数据库连接失败、SQL语法错误,你都看不到任何提示!这是最致命的问题,必须改成打印异常或弹出错误提示,比如:catch (Exception e) { e.printStackTrace(); // 控制台打印异常,方便调试 JOptionPane.showMessageDialog(null, "操作失败:" + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE); }PreparedStatement的executeQuery用法错误:你已经用
pst = conn.prepareStatement(sql)预编译了SQL,调用executeQuery()时不需要再传sql参数,而且没有把查询结果赋值给rs。正确写法是:pst = conn.prepareStatement(sql); rs = pst.executeQuery(); // 这里不要传sql参数另外,
rs变量需要提前声明(比如ResultSet rs = null;)。重复使用同一个PreparedStatement执行更新:用同一个
pst先执行查询再执行更新会引发问题,应该创建新的PreparedStatement执行更新操作。SQL注入风险:直接拼接字符串生成SQL(
"select * from Login where username='" + user + "'")容易被攻击,建议替换为参数占位符的写法。
修复后的完整代码示例
private void changeActionPerformed(java.awt.event.ActionEvent evt) { String user = username.getText(); String pass = password.getText(); String newp = newpass.getText(); // 使用参数占位符的SQL语句 String checkSql = "SELECT password FROM Login WHERE username = ?"; String updateSql = "UPDATE Login SET password = ? WHERE username = ?"; try { // 校验用户与密码 PreparedStatement checkStmt = conn.prepareStatement(checkSql); checkStmt.setString(1, user); ResultSet rs = checkStmt.executeQuery(); if (rs.next()) { if (rs.getString("password").equals(pass)) { // 执行密码更新 PreparedStatement updateStmt = conn.prepareStatement(updateSql); updateStmt.setString(1, newp); updateStmt.setString(2, user); int rowsUpdated = updateStmt.executeUpdate(); if (rowsUpdated > 0) { JOptionPane.showMessageDialog(null, "Password Changed!"); // 清空输入框 password.setText(""); newpass.setText(""); } updateStmt.close(); } else { JOptionPane.showMessageDialog(null, "Invalid username or password", "Access Denied", JOptionPane.ERROR_MESSAGE); } } else { JOptionPane.showMessageDialog(null, "Wrong username!"); } rs.close(); checkStmt.close(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(null, "操作失败:" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } }
内容的提问来源于stack exchange,提问作者Byakuran

