在Java企业级应用开发中,数据库操作是不可或缺的核心功能。JDBC(Java Database Connectivity)作为Java语言与数据库交互的标准API,是每位Java开发者必须掌握的技能。本文将深入探讨JDBC的核心组件,包括DriverManager、Connection的使用,PreparedStatement防SQL注入机制,以及高性能连接池(Druid/HikariCP)的实战应用,帮助你构建安全高效的数据库访问层。
JDBC采用分层设计,主要包含以下组件:
DriverManager:管理数据库驱动,建立连接
Connection:表示与特定数据库的连接会话
Statement/PreparedStatement:执行SQL语句
ResultSet:封装查询结果集
传统获取数据库连接的方式:
// 1. 加载驱动(JDBC 4.0+后自动加载,可省略)
Class.forName("com.mysql.cj.jdbc.Driver");
// 2. 获取连接
String url = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC";
String username = "root";
String password = "123456";
try (Connection conn = DriverManager.getConnection(url, username, password)) {
// 数据库操作...
} catch (SQLException e) {
e.printStackTrace();
}
关键参数说明:
useSSL=false
:禁用SSL(生产环境应启用)
serverTimezone=UTC
:设置时区避免时间问题
try-with-resources
:自动关闭资源,防止泄漏
方法 | 说明 |
---|---|
createStatement() |
创建Statement对象 |
prepareStatement(sql) |
创建预编译Statement |
setAutoCommit(false) |
关闭自动提交,开启事务 |
commit() /rollback() |
提交/回滚事务 |
close() |
释放连接资源 |
危险示例:
String username = request.getParameter("username");
String sql = "SELECT * FROM users WHERE username = '" + username + "'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
当输入username
为admin' --
时,SQL变为:
SELECT * FROM users WHERE username = 'admin' --'
这将导致注释掉后续条件,可能获取管理员权限!
预编译语句通过参数化查询实现安全:
SQL模板提前编译
参数值单独传输
数据库区分代码与数据
安全示例:
String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username); // 自动处理特殊字符
ResultSet rs = pstmt.executeQuery();
String sql = "INSERT INTO users(username, email) VALUES(?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
for (User user : userList) {
pstmt.setString(1, user.getUsername());
pstmt.setString(2, user.getEmail());
pstmt.addBatch(); // 添加到批处理
}
int[] results = pstmt.executeBatch(); // 执行批处理
conn.commit(); // 提交事务
性能对比:
单条插入1000条:约1200ms
批处理1000条:约150ms(提升8倍)
直接获取连接的缺点:
每次建立TCP连接开销大
并发请求时连接数暴增
连接资源管理复杂
连接池优势:
复用连接:减少创建/销毁开销
限制最大连接数:防止数据库过载
健康检查:自动剔除失效连接
配置示例:
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("root");
config.setPassword("123456");
config.setMaximumPoolSize(20); // 最大连接数
config.setMinimumIdle(5); // 最小空闲连接
config.setConnectionTimeout(30000); // 获取连接超时时间
config.setIdleTimeout(600000); // 空闲连接超时时间
config.setMaxLifetime(1800000);// 连接最大存活时间
HikariDataSource dataSource = new HikariDataSource(config);
性能优化参数:
connectionTestQuery="SELECT 1"
:连接健康检查SQL
leakDetectionThreshold=60000
:检测连接泄漏(毫秒)
配置示例:
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setInitialSize(5); // 初始化连接数
dataSource.setMaxActive(20); // 最大连接数
dataSource.setMinIdle(5); // 最小空闲连接
dataSource.setMaxWait(60000); // 获取连接等待超时时间
// 监控统计相关配置
dataSource.setFilters("stat,wall");
dataSource.setValidationQuery("SELECT 1");
dataSource.setTestWhileIdle(true);
特色功能:
SQL监控:统计执行性能、识别慢查询
防火墙:防御SQL注入
加密支持:数据库密码加密
Spring集成:完美支持Spring Boot
特性 | HikariCP | Druid |
---|---|---|
启动速度 | ⚡️ 极快 | 中等 |
并发性能 | 最高 | 高 |
监控功能 | 基础 | 非常完善 |
SQL防火墙 | 不支持 | 支持 |
适用场景 | 极致性能需求 | 需要监控的企业应用 |
基准测试数据(100并发循环10000次):
HikariCP:平均响应时间12ms
Druid:平均响应时间18ms
传统连接池:平均响应时间35ms
错误示例:
Connection conn = null;
try {
conn = dataSource.getConnection();
// ...操作数据库
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close(); // 可能忘记关闭其他资源
}
}
推荐做法:
try (Connection conn = dataSource.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
// 处理结果集
}
} // 自动调用close()方法
Connection conn = null;
try {
conn = dataSource.getConnection();
conn.setAutoCommit(false); // 开启事务
// 执行多个SQL操作
updateAccount(conn, from, -amount);
updateAccount(conn, to, amount);
conn.commit(); // 提交事务
} catch (SQLException e) {
if (conn != null) {
conn.rollback(); // 回滚事务
}
throw new RuntimeException("转账失败", e);
} finally {
if (conn != null) {
conn.setAutoCommit(true); // 恢复自动提交
conn.close();
}
}
连接泄漏:
现象:连接数达到上限后无法获取新连接
解决:检查是否所有Connection都正确关闭
慢查询:
现象:某些操作响应极慢
解决:使用Druid监控识别慢SQL并优化
连接超时:
现象:获取连接时抛出TimeoutException
解决:调整连接池大小或优化查询性能
application.yml
配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
添加依赖:
com.alibaba
druid-spring-boot-starter
1.2.8
配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5
max-active: 20
min-idle: 5
filters: stat,wall
JDBC作为Java数据库访问的基石,其正确使用直接影响到应用的安全性和性能。通过本文的学习,你应该已经掌握了:
DriverManager和Connection的核心用法
PreparedStatement防SQL注入机制
连接池(Druid/HikariCP)的配置与优化
进一步学习建议:
研究MyBatis/Hibernate等ORM框架的JDBC封装
探索分布式事务(XA/JTA)的实现
学习数据库读写分离的配置
了解JDBC 4.3的新特性
如果你在实践过程中遇到任何问题,欢迎在评论区留言讨论。觉得本文有帮助的话,别忘了点赞收藏哦!