应使用 preparedstatement 替代 statement,预编译一次、参数化执行,安全高效;复用 preparedstatement 实例(threadlocal 或类成员),配合 hikaricp 连接池与 leakdetectionthreshold 等配置防泄漏。

用 PreparedStatement 替代 Statement
Statement 每次执行都要解析 SQL、编译执行计划,高并发下开销大且易受 SQL 注入攻击。PreparedStatement 预编译一次,参数化执行,既安全又高效。
关键点:
- SQL 字符串固定不变时,只创建一次 PreparedStatement 实例,反复 setParameter + executeQuery/executeUpdate
- 避免在循环内调用 connection.prepareStatement(sql),应在循环外初始化
- 参数类型要匹配(如 setInt、setString),避免隐式转换带来的额外开销
连接必须从连接池获取,且严格归还
高并发下频繁新建 Connection 是性能瓶颈。必须使用 HikariCP 等连接池,杜绝 DriverManager 直连。
正确做法:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 通过 DataSource 获取 Connection,用完不 close(),而是由 try-with-resources 自动归还到池中
- Connection、PreparedStatement、ResultSet 全部纳入 try-with-resources 块,确保异常时也释放资源
- 禁用 long-running 线程长期持有 Connection;每个数据库操作应“即取即用即还”
避免 Statement 层级的重复创建
即使用了 PreparedStatement,若每次查询都 new 一个新实例,仍会带来对象分配压力和 GC 负担。
优化方式:
- 将 PreparedStatement 声明为类成员变量(或缓存在 ThreadLocal 中),复用同一实例
- 注意:PreparedStatement 不是线程安全的,多线程场景下不能全局共享单个实例,推荐按线程隔离(ThreadLocal)或按业务逻辑复用范围控制
- 如果 SQL 模板多样(如不同 where 条件),可借助 PreparedStatement 缓存机制(HikariCP 默认开启 prepared-statement-cache-size)
配合连接池参数与监控防泄漏
复用的前提是连接不被泄露。光靠代码规范不够,需配置兜底机制。
必要设置(以 HikariCP 为例):
- leakDetectionThreshold=60000:检测超 60 秒未归还的 Connection,日志告警定位泄露点
- maxLifetime=1800000(30 分钟):强制刷新老化连接,避免 MySQL wait_timeout 导致通信失败
- connectionTimeout=30000:获取连接等待上限,防止线程无限阻塞
- 启用监控(如 metricsTrackerFactory)观察 active/idle 连接数、等待队列长度等指标
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










