PreparedStatement
:,1. 编写UPDATE模板:UPDATE 表名 SET 列1=?, 列2=? WHERE 条件
,2. 通过PreparedStatement
预编译,设置参数值,3. 调用executeUpdate()
执行,4. 处理异常并关闭资源,示例:,“java,String sql = "UPDATE users SET name=?, age=? WHERE id=?";,try (PreparedStatement pstmt = conn.prepareStatement(sql)) {, pstmt.setString(1, "新名字");, pstmt.setInt(2, 30);, pstmt.setInt(3, 1001);, int rows = pstmt.executeUpdate(); // 返回受影响行数,},
“基础更新语句写法
使用Statement
执行简单更新(适用于静态SQL):
String sql = "UPDATE users SET name='张三', age=30 WHERE id=1001"; try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS); Statement stmt = conn.createStatement()) { int rowsAffected = stmt.executeUpdate(sql); System.out.println("更新行数: " + rowsAffected); // 输出受影响行数 } catch (SQLException e) { e.printStackTrace(); }
安全更新:PreparedStatement(防SQL注入)
强烈推荐使用参数化查询处理动态值:
String sql = "UPDATE products SET price=?, stock=? WHERE product_id=?"; try (Connection conn = dataSource.getConnection(); PreparedStatement pstmt = conn.prepareStatement(sql)) { // 设置参数 (索引从1开始) pstmt.setDouble(1, 299.99); // price pstmt.setInt(2, 50); // stock pstmt.setString(3, "P1005"); // product_id int updatedRows = pstmt.executeUpdate(); if (updatedRows > 0) { System.out.println("商品数据更新成功"); } } catch (SQLException ex) { System.err.println("更新异常: " + ex.getMessage()); }
关键注意事项
-
WHERE子句必要性
缺少WHERE条件将更新全表数据:// 危险操作!更新所有记录 String unsafeSql = "UPDATE employees SET salary=10000";
-
批量更新优化性能
使用addBatch()
提升大批量操作效率:try (PreparedStatement pstmt = conn.prepareStatement("UPDATE log SET status=?")) { for (LogEntry log : logEntries) { pstmt.setString(1, log.getStatus()); pstmt.addBatch(); // 加入批处理 } int[] results = pstmt.executeBatch(); // 执行批处理 }
-
事务控制保证原子性
确保多步骤更新要么全成功要么全失败:conn.setAutoCommit(false); // 关闭自动提交 try { updateAccountBalance(conn, "A001", -500); // 扣款 updateAccountBalance(conn, "B002", +500); // 加款 conn.commit(); // 提交事务 } catch (SQLException e) { conn.rollback(); // 回滚事务 }
完整示例代码(含资源关闭)
import java.sql.*; public class SQLUpdateExample { static final String JDBC_URL = "jdbc:mysql://localhost:3306/mydb"; static final String USER = "root"; static final String PASSWORD = "securePass123!"; public static void main(String[] args) { String updateSQL = "UPDATE orders SET status = ? WHERE order_id = ?"; try (Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD); PreparedStatement pstmt = conn.prepareStatement(updateSQL)) { // 设置参数 pstmt.setString(1, "SHIPPED"); // 新状态 pstmt.setInt(2, 20045); // 订单ID // 执行更新 int affectedRows = pstmt.executeUpdate(); System.out.println("已更新订单状态,受影响行数: " + affectedRows); } catch (SQLException se) { // 打印详细错误日志 System.err.println("SQL错误代码: " + se.getErrorCode()); System.err.println("SQL状态: " + se.getSQLState()); se.printStackTrace(); } } }
最佳实践总结
-
始终使用PreparedStatement
- 防止SQL注入攻击
- 自动处理特殊字符转义(如单引号)
- 提升查询性能(数据库预编译)
-
资源自动关闭
使用try-with-resources
(Java 7+)确保Connection
、Statement
等资源自动释放。 -
严谨的错误处理
- 捕获
SQLException
并记录错误码 (getErrorCode()
) 和SQL状态 (getSQLState()
) - 使用事务的
rollback()
保证数据一致性
- 捕获
-
验证更新结果
通过executeUpdate()
返回值确认实际更新的行数,避免“静默失败”。
引用说明:本文代码基于JDBC 4.2规范编写,遵循Oracle官方文档和OWASP SQL注入防护建议,关键安全实践参考自《Java安全编码标准》(CERT)。
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/7876.html