conn.rollback()抛出未处理SQLException,如何正确使用commit()?
解决事务回滚时的SQLException问题
嘿,我完全懂你现在的困惑——明明已经在catch块里捕获SQLException了,怎么调用conn.rollback()还会抛出未处理的异常?别急,这是因为rollback()方法本身也会抛出SQLException,它和你之前捕获的SQL操作异常是同一类,所以在catch块里调用它时,这个新的异常没有被处理,编译器自然会报错。
接下来给你几个可行的解决方案,顺便帮你优化下代码里的其他小问题:
方案1:在catch块内嵌套try-catch处理回滚异常
这是最直接的方式,把conn.rollback()放在一个内部try-catch里,专门处理回滚时可能出现的异常:
try { conn.setAutoCommit(false); // 你的SQL语句和循环逻辑... conn.commit(); } catch (SQLException e) { System.out.println("ERRRROOOOOOORRRRR"); // 嵌套try-catch处理回滚异常 try { if (conn != null && !conn.isClosed()) { conn.rollback(); System.out.println("事务已回滚"); } } catch (SQLException rollbackEx) { System.err.println("回滚失败:" + rollbackEx.getMessage()); } } finally { // 别忘了恢复自动提交并关闭资源 try { if (conn != null) { conn.setAutoCommit(true); conn.close(); } } catch (SQLException ex) { ex.printStackTrace(); } }
方案2:使用try-with-resources(推荐)
Java 7及以上的try-with-resources语法可以自动关闭实现了AutoCloseable接口的资源(比如Connection、PreparedStatement、ResultSet),不仅代码更简洁,还能避免资源泄漏,同时异常处理也更清晰:
// 用try-with-resources自动管理Connection try (Connection conn = getYourConnection()) { // 替换成你的数据库连接获取逻辑 conn.setAutoCommit(false); // 同样用try-with-resources管理PreparedStatement try (PreparedStatement selectStatement = conn.prepareStatement("SELECT l.toy_id FROM LETTER l WHERE toy_id=?"); PreparedStatement deleteStatement = conn.prepareStatement("DELETE FROM TOY WHERE toy_id=?"); PreparedStatement updateStatement = conn.prepareStatement("INSERT INTO TOY (toy_id, toy_name, price,toy_type, manufacturer) VALUES (?,?,?,?,?)")) { for (List<String> row : fileContents) { int toy_id = getToyId(row); selectStatement.setInt(1, toy_id); try (ResultSet rs = selectStatement.executeQuery()) { if (!rs.next()) { // 用rs.next()判断结果集是否为空更通用 // 执行删除 deleteStatement.setInt(1, toy_id); deleteStatement.executeUpdate(); } else { // 执行更新(注意:你原来的代码只设了toy_id,其他参数没传会报错!) updateStatement.setInt(1, toy_id); updateStatement.setString(2, row.get(1)); // 假设row索引1对应toy_name updateStatement.setDouble(3, Double.parseDouble(row.get(2))); // price updateStatement.setString(4, row.get(3)); // toy_type updateStatement.setString(5, row.get(4)); // manufacturer updateStatement.executeUpdate(); } } } conn.commit(); } } catch (SQLException e) { System.out.println("ERRRROOOOOOORRRRR:" + e.getMessage()); // 处理回滚异常 try (Connection conn = getYourConnection()) { // 或确保conn未关闭时直接使用 if (conn != null && !conn.isClosed()) { conn.rollback(); System.out.println("事务已回滚"); } } catch (SQLException rollbackEx) { System.err.println("回滚失败:" + rollbackEx.getMessage()); } }
额外提醒几个代码里的小问题
- 变量名
UpdateStatement不符合Java小驼峰命名规范,建议改成updateStatement; - 更新操作时,你只设置了
toy_id,另外4个必填参数都没赋值,执行时肯定会抛出SQL异常,记得把row里对应的字段补全; - 用
rs.next()代替rs.first()判断结果集是否为空更稳妥,部分JDBC驱动可能不支持first()方法; - 无论事务成功还是失败,都要确保数据库连接等资源被正确关闭,避免连接池泄漏。
内容的提问来源于stack exchange,提问作者frackme
相关产品推荐
相关产品推荐

