数据库访问
database-access、JDBC 与连接池直觉。
30 分钟
数据库访问
Spring Data JPA 把 SQL 藏得很深,但排障时你仍需要 JDBC 与连接池 的直觉。本课衔接 java-core-essentials 的 I/O 与异常处理,为 orm-essentials 与 spring-boot-essentials 的 DataSource 配置打地基。
学习目标
- 用 JDBC 完成「连接 → 预编译 → 查询 → 关闭」完整链路
- 理解连接池为何存在,以及 HikariCP 的核心参数
- 区分 JDBC 模板、MyBatis 与 JPA 的适用场景
JDBC 最小可用示例
public record User(long id, String email) {}
public class UserRepository {
private final DataSource dataSource;
public UserRepository(DataSource dataSource) {
this.dataSource = dataSource;
}
public Optional<User> findById(long id) throws SQLException {
String sql = "SELECT id, email FROM users WHERE id = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setLong(1, id);
try (ResultSet rs = ps.executeQuery()) {
if (!rs.next()) {
return Optional.empty();
}
return Optional.of(new User(rs.getLong("id"), rs.getString("email")));
}
}
}
}
要点:始终用 PreparedStatement 防 SQL 注入;用 try-with-resources 确保连接归还池子。
连接池:HikariCP 配置直觉
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/demo");
config.setUsername("app");
config.setPassword("secret");
config.setMaximumPoolSize(10); // 并发上限,不是越大越好
config.setConnectionTimeout(5_000); // 借连接等待毫秒
config.setPoolName("demo-pool");
DataSource ds = new HikariDataSource(config);
| 参数 | 含义 | 常见误区 |
|---|---|---|
| maximumPoolSize | 同时借出的连接数 | 设成 100 反而拖垮 DB |
| connectionTimeout | 池满时等待时间 | 与 SQL 执行超时不是一回事 |
| idleTimeout | 空闲连接回收 | 过短导致频繁建连 |
Spring Boot 默认 HikariCP;你在 application.yml 里改的 spring.datasource.hikari.* 就是这里。
选型速查
- 纯 JDBC + 手写 SQL:报表、批量 ETL、极致 SQL 控制