☕ 第十一章 JDBC
📝 一句话概括

第十一章走完一条线:认合同(11.1)→ 摸方法(11.2)→ 真跑通(11.3)→ 配池子(11.4)→ 请管家(11.5)——从「会连数据库」到「优雅地连数据库」,JDBC 这座山翻完了。

一、五节串线

节 主题 一句话记忆点
11.1 什么是 JDBC Sun 定的总合同,厂商写实现装 jar,换库只换 jar+url
11.2 常用 API 四大件(调度员/电话线/传话筒/快递箱),ResultSet 光标从表头前出发
11.3 JDBC 编程 三件准备 + Demo13 CRUD 四连,学会看异常信息是第一基本功
11.4 数据库连接池 连接的租车行,池版 close 不是关闭是归还
11.5 DbUtils 现成管家:QueryRunner 管执行,Handler 管形状,一行查全表

二、概念速查

  1. JDBC:Java 官方定的操作数据库接口规范(4.3 接口合同的最大实战)
  2. 驱动 jar:数据库厂商按合同写的实现类压缩包,导入后 Add as Library 才生效
  3. 四大件:DriverManager(调度员)→ Connection(电话线)→ Statement(传话筒)→ ResultSet(快递箱)
  4. url 三段式:jdbc:mysql://localhost:3306/库名?serverTimezone=...
  5. 两路分工:executeUpdate 增删改返回行数;executeQuery 查询返回结果集,串门即炸
  6. 光标:ResultSet 初始停在表头前,必须先 next();取值列号从 1 起,推荐按列名
  7. 连接池:预建连接循环借还,DataSource 是 JDK 第二份合同,Druid 是热门实现
  8. 池版 close:不是关闭,是归还——只借不还池子卡死
  9. QueryRunner:DbUtils 执行者,update / query 两大方法
  10. ResultSetHandler:装配工——BeanHandler 一条、BeanListHandler 多行、ScalarHandler 聚合值
  11. 装配底层:反射拿列名拼 setXxx(9.1 正式上岗),所以属性名 = 列名是保命规矩
  12. SQL 注入:拼接 SQL 的安全坑,属于 PreparedStatement 的战场(DbUtils 不负责防)

三、代码模板(背这四段)

模板 1:五步骨架(11.2)

Connection conn = DriverManager.getConnection(URL, USER, PWD);
Statement stmt = conn.createStatement();
int rows = stmt.executeUpdate(sql);        // 增删改
ResultSet rs = stmt.executeQuery(sql);     // 查询
// while(rs.next()) { rs.getXxx("列名"); }
// 三资源进 try 括号,自动倒序关

模板 2:异常对症(11.3)

ClassNotFoundException  → jar 没导入 / 没 Add as Library
Access denied           → 账号或密码错
Unknown database        → url 里库名写错

模板 3:连接池替换(11.4)

DataSource ds = DruidDataSourceFactory.createDataSource(prop);
Connection conn = ds.getConnection();      // 只换这一行,其余不动

模板 4:DbUtils 查询(11.5)

QueryRunner qr = new QueryRunner(ds);
List<Student> list = qr.query(sql, new BeanListHandler<>(Student.class));
Long count = qr.query("SELECT COUNT(*) FROM student", new ScalarHandler<>());

四、五大名坑回顾

  1. 光标没挪就取值——Before start of result set,先 next() 再说话
  2. 列号从 0 取——SQL 世界从 1 数数,rs.getInt(0) 直接炸
  3. update 跑 SELECT——两路串门抛 SQLException,管家也救不了
  4. 池子只借不还——连接用完忘 close(归还),池子耗尽新请求全体超时
  5. 属性名 ≠ 列名——DbUtils 装配默默丢列,查出来是 null 还不报错

五、收官暗线

本章表面学「怎么连数据库」,暗地里把前面的理论全搬上了生产现场:

一句话收官:JDBC 是你第一次站在「接口是别人的、实现是别人的、你只管调」的世界门口——这条门后面就是真正的企业级开发(MyBatis、Spring 全在这个思路上加盖)。

六、跨章连线

七、毕业大题:手写「员工管理小系统」核心层

题目:用 Druid + DbUtils 完成三件事:①按姓名查一个员工并打印;②查全表返回 List<Emp>;③统计总人数。要求说出每步用了什么、为什么。

参考骨架:

DataSource ds = DruidFactory.getDataSource();       // 租车行
QueryRunner qr = new QueryRunner(ds);               // 管家

Emp e = qr.query("SELECT * FROM emp WHERE name=?",
        new BeanHandler<>(Emp.class), name);        // ① 一条 → BeanHandler
List<Emp> all = qr.query("SELECT * FROM emp",
        new BeanListHandler<>(Emp.class));          // ② 多行 → BeanListHandler
Long total = qr.query("SELECT COUNT(*) FROM emp",
        new ScalarHandler<>());                     // ③ 聚合 → ScalarHandler
✅ 自检清单(全打勾才算毕业)
  1. 能说清 JDBC 合同和驱动 jar 的关系,以及为什么换数据库不用改业务代码
  2. 四大件各是什么角色,两路方法(update/query)怎么分工
  3. ResultSet 光标的初始位置和 next() 的返回值含义
  4. 连接池解决什么问题,池版 close 的语义变化
  5. 三大 Handler 各对应什么查询场景
  6. 能说出「属性名 = 列名」背后的反射原理

下一步学什么

相关笔记