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));
}

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

相关推荐
ClouGence23 分钟前
SQL Server CDC 能放到 Always On 备库读吗?一文讲透原理与实践
数据库·sql server
你好潘先生2 小时前
别再记命令了,用 yeero do 说句人话就能跑脚本,而且不烧 token
服务器·python·命令行
Agent_大师2 小时前
WebSocket 行情重连成功,K线缺口不会自动消失
python
荣码2 小时前
LLM结构化输出:让AI返回JSON而不是废话,我踩了4个坑
java·python
copyer_xyf3 小时前
FastAPI 如何连接 MySQL
后端·python
apocelipes16 小时前
常用编程语言和库的正则表达式性能对比
c语言·c++·python·性能优化·golang·开发工具和环境
先吃饱再说18 小时前
存储的进化:从 MySQL 到浏览器缓存,数据到底住在哪?
数据库
用户83562907805118 小时前
使用 Python 在 PDF 中创建与管理书签
后端·python
Nturmoils18 小时前
字段太多看不全,ksql 的展开模式和输出控制怎么用
数据库·后端
Databend20 小时前
Agent 轨迹分析与归因的数据工程实践
大数据·数据库·agent