JDBC编程规范:PreparedStatement与事务管理

PreparedStatement的使用规范

使用PreparedStatement替代Statement能有效防止SQL注入攻击,提高执行效率。创建PreparedStatement时应使用参数化查询:

java 复制代码
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();

参数索引从1开始,必须为每个参数设置合适的类型(setInt/setString等)。执行后必须关闭资源:

java 复制代码
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
    // 设置参数并执行
} catch (SQLException e) {
    // 异常处理
}

批处理操作优化

对于批量数据操作,应使用addBatch()和executeBatch()方法:

java 复制代码
PreparedStatement pstmt = connection.prepareStatement("INSERT INTO logs VALUES(?, ?)");
for (Log log : logList) {
    pstmt.setString(1, log.getId());
    pstmt.setTimestamp(2, log.getTime());
    pstmt.addBatch();
}
int[] results = pstmt.executeBatch();

批处理大小建议控制在100-1000条之间,过大的批处理可能导致内存问题。

事务管理基本模式

JDBC事务应遵循ACID原则,默认自动提交需关闭:

java 复制代码
connection.setAutoCommit(false);
try {
    // 执行多个SQL操作
    connection.commit();
} catch (SQLException e) {
    connection.rollback();
} finally {
    connection.setAutoCommit(true);
}

事务隔离级别应根据业务需求设置:

modelscope.cn/learn/70890

modelscope.cn/learn/70889

modelscope.cn/learn/70886

modelscope.cn/learn/70885

modelscope.cn/learn/70882

modelscope.cn/learn/70880

modelscope.cn/learn/70878

modelscope.cn/learn/70876

modelscope.cn/learn/70875

modelscope.cn/learn/70872

modelscope.cn/learn/70870

modelscope.cn/learn/70868

modelscope.cn/learn/70867

modelscope.cn/learn/70864

modelscope.cn/learn/70863

modelscope.cn/learn/70860

modelscope.cn/learn/70859

modelscope.cn/learn/70856

modelscope.cn/learn/70855

modelscope.cn/learn/70852

java 复制代码
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

事务超时设置

为防止长时间运行的事务,应设置超时时间:

java 复制代码
int timeoutSeconds = 30;
connection.setNetworkTimeout(executor, timeoutSeconds * 1000);

对于分布式系统,需考虑XA事务或使用JTA实现。

连接池与事务关联

从连接池获取连接时,必须确保事务结束后重置连接状态:

java 复制代码
try (Connection conn = dataSource.getConnection()) {
    conn.setAutoCommit(false);
    // 业务操作
    conn.commit();
} catch (Exception e) {
    // 异常时自动回滚
}

连接必须在使用后立即关闭,避免连接泄漏。

异常处理规范

捕获SQLException时应包含详细信息:

java 复制代码
catch (SQLException e) {
    logger.error("SQLState: " + e.getSQLState() 
        + " ErrorCode: " + e.getErrorCode(), e);
    throw new DataAccessException(e);
}

对可恢复错误(如死锁)应实现重试机制。

元数据缓存优化

频繁使用的PreparedStatement可缓存:

java 复制代码
Map<String, PreparedStatement> statementCache = new LRUCache<>(100);
PreparedStatement getCachedStatement(String sql) {
    return statementCache.computeIfAbsent(sql, 
        k -> connection.prepareStatement(k));
}

注意缓存大小需根据应用负载调整,避免内存溢出。

相关推荐
我星期八休息2 小时前
IT疑难杂症诊疗室:AI时代工程师Superpowers进化论
linux·开发语言·数据结构·人工智能·python·散列表
代码小书生2 小时前
math,一个基础的 Python 库!
人工智能·python·算法
卧室小白2 小时前
Redis-哨兵模式
数据库·redis·缓存
GottdesKrieges2 小时前
OceanBase恢复常见问题
java·数据库·oceanbase
leo825...2 小时前
Claude Code Skills 清单(本地)
java·python·ai编程
其实防守也摸鱼2 小时前
CTF密码学综合教学指南--第三章
开发语言·网络·python·安全·网络安全·密码学
卧室小白2 小时前
redis-配置
数据库·redis·缓存
A7bert7772 小时前
【YOLOv8pose部署至RDK X5】模型训练→转换bin→Sunrise 5部署
c++·python·深度学习·yolo·目标检测
向風而行3 小时前
MySQL详解
数据库·mysql