03-JDBC 与数据库连接池
对应原始资料:
数据库_day04、数据库阶段_day06
一、JDBC 概述
JDBC(Java Database Connectivity)是 Java 操作关系型数据库的一套规范/接口,各数据库厂商提供实现(驱动)。
Java 程序 → JDBC 接口 → 驱动(厂商) → 数据库二、JDBC 快速入门
1. 步骤
- 导入驱动 jar(mysql-connector-java)。
- 注册驱动(JDK 6 后可省略,SPI 自动加载)。
- 获取连接。
- 定义 SQL。
- 获取执行对象 Statement。
- 执行 SQL。
- 处理结果。
- 释放资源。
2. 代码
java
// 1. 导入 jar(pom 中引入 mysql-connector-java)
// 2. 注册驱动(可省)
Class.forName("com.mysql.cj.jdbc.Driver");
// 3. 获取连接
String url = "jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC&characterEncoding=utf8";
Connection conn = DriverManager.getConnection(url, "root", "123456");
// 4. SQL
String sql = "SELECT * FROM emp WHERE id = ?";
// 5. PreparedStatement(防 SQL 注入)
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, 1);
// 6. 执行
ResultSet rs = ps.executeQuery(); // 查询
// int i = ps.executeUpdate(); // 增删改,返回影响行数
// 7. 处理结果
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println(id + " " + name);
}
// 8. 释放资源(倒序关)
rs.close();
ps.close();
conn.close();三、PreparedStatement vs Statement
| 维度 | Statement | PreparedStatement |
|---|---|---|
| SQL 注入 | 有风险 | 预编译防注入 |
| 性能 | 每次编译 | 可缓存执行计划 |
| 参数 | 拼字符串 | 用 ? 占位 |
永远用 PreparedStatement,不要拼字符串。
四、JDBC 事务管理
默认每条 SQL 自动提交。手动事务:
java
try {
conn.setAutoCommit(false);
ps1.executeUpdate();
ps2.executeUpdate();
conn.commit();
} catch (Exception e) {
conn.rollback();
e.printStackTrace();
} finally {
conn.setAutoCommit(true);
// 关资源
}五、ResultSet 元数据
java
ResultSetMetaData md = rs.getMetaData();
int count = md.getColumnCount();
for (int i = 1; i <= count; i++) {
String name = md.getColumnName(i);
String type = md.getColumnTypeName(i);
}可用于通用查询(把结果集映射成 Map / 对象)。
六、数据库连接池(重点)
1. 为什么用连接池
- 每次新建/关闭连接很耗时。
- 预先创建一批连接放在池里,复用,提升性能。
2. 常见连接池
- Druid(阿里巴巴):监控强、性能好,国内主流。
- HikariCP:SpringBoot 默认,号称最快。
- C3P0:老牌(资料中有补充)。
3. Druid 使用
java
Properties props = new Properties();
props.load(new FileInputStream("druid.properties"));
DataSource ds = DruidDataSourceFactory.createDataSource(props);
try (Connection conn = ds.getConnection()) {
// 用 conn
}druid.properties:
properties
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db1
username=root
password=123456
initialSize=5
maxActive=20
maxWait=3000连接池 = DataSource(数据源),由它统一管理 Connection。
七、JDBC 工具类封装
把重复代码抽成工具类:
java
public class JDBCUtil {
private static final DataSource DS;
static {
try {
Properties p = new Properties();
p.load(JDBCUtil.class.getClassLoader().getResourceAsStream("druid.properties"));
DS = DruidDataSourceFactory.createDataSource(p);
} catch (Exception e) { throw new RuntimeException(e); }
}
public static Connection getConnection() throws SQLException { return DS.getConnection(); }
public static DataSource getDataSource() { return DS; }
public static void close(Connection c, Statement s, ResultSet r) {
if (r != null) try { r.close(); } catch (Exception e) {}
if (s != null) try { s.close(); } catch (Exception e) {}
if (c != null) try { c.close(); } catch (Exception e) {}
}
}八、Apache DbUtils(了解)
Apache Commons DbUtils 简化了结果集处理:
java
QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
List<Emp> list = qr.query("SELECT * FROM emp",
new BeanListHandler<>(Emp.class));练习建议
- 用 JDBC 完成 emp 表的 CRUD。
- 用 PreparedStatement 实现登录验证(体会 SQL 注入防护)。
- 用 Druid 改造上面的程序,对比连接耗时。
- 封装一个通用查询方法:传入 SQL 和参数,返回
List<Map>。 - 完成「黑马商城」资料中的登录注册(基于 JDBC)。