JDBC 与数据库事务核心

第一部分:JDBC 驱动与 URL

1.1 JDBC 的定位

  • JDBC 是 Java 连接数据库的接口规范,原生操作数据库就靠它;后来才有 Hibernate、MyBatis 等封装产品。
  • JDBC 实现类由各数据库厂商提供,叫驱动类,如 MySQL、Oracle 各有自己的驱动,它是代码与库之间的桥梁,使用需导入对应依赖包。

重点:驱动版本最好与数据库版本匹配,库是 5 就导 5 的驱动,8 就导 8 的;高版本驱动可兼容低版本库(如 8 驱连 5 库),但不建议这么做。

易错点:不要把 JDBC 当实现类------它只是规范,真正干活的是厂商驱动。掌握 JDBC 接口方法后,换数据库只换驱动即可。

1.2 JDBC 快速入门与常用类

  • 准备库、表和数据,再按固定流程写程序:加载驱动、获取连接、编写并执行 SQL、遍历结果集、关闭资源。
  • 常用类中,DriverManager 负责加载驱动类。
  • URL 是重点,由主协议、子协议、主机 IP、数据库名组成。

易错点:MySQL 8 版本 URL 必须加时区,5 版本不需要,否则 8 版会报错。是否加 UTF-8 编码,看数据库编码是否一致,一致用默认即可。

1.3 SQL 操作分类

  • JDBC 执行 SQL 分查询和增删改(update)两类;另有批处理、清理等少用操作了解即可。
  • 结果集通过 get 类型方法取字段并释放资源。
  • SQL 注入此前已讲。

易错点:不要把这些普通 SQL 操作误认涉事务,只有事务相关才是重点。

1.4 JDBC 七步定位问题

  • 若对 JDBC 操作数据库的七个步骤都不理解,应先确认班级此前是否讲过该内容。
  • 找到之前和当天下午的录屏重看一遍,结合图解把步骤再过一遍。

重点:学习时必须定位到具体哪一步有问题,而非笼统说"都不懂"。难点是步骤间的顺序与依赖关系易混淆,需对照视频和图解逐点梳理。


第二部分:事务概念

2.1 事务概述

事务是数据库提供的一个特性:组成各个数据的执行单元,要么都成功,要么都不成功。

转账例子:冠希给美美转 1000 元。

复制代码
先给冠希扣除 1000 元
再给美美加上 1000 元
事务结束
  • 背后是两条 SQL,但属共同体。
  • 事务前后总数据量不变:如两人各 1 万,转后总额仍 2 万。

易错点:不要把事务里多条 SQL 当独立操作,必须捆绑看成一个单元。

难点:理解"最小逻辑单元"不可分------可类比打包快递,拆开就失效。

2.2 事务控制的位置

  • 事务控制是在数据库客户端层面进行的,如 cmd 窗口或 Navicat 这类图形化工具,都属于 MySQL 客户端操作,不属于高级语言操作数据库的范畴。
  • 例:用 mysql -u root -p 登录,切换到 jdbc demo 库,在数据库层面展示如何控制事务、看清事务全貌。

易错点:不要以为事务控制写在 Java 等代码里才算,客户端直接发指令也是正经的事务控制方式。


第三部分:MySQL 中操作事务

3.1 准备数据

建表语句:

复制代码
create table t_account(
    id int primary key auto_increment,
    username varchar(20),
    money double
);

插入测试数据:

复制代码
insert into t_account values (null,'美美',10000);
insert into t_account values (null,'冠希',10000);
insert into t_account values (null,'小凤',10000);
insert into t_account values (null,'熊大',10000);
insert into t_account values (null,'熊二',10000);

3.2 默认事务机制

  • MySQL 默认自动提交:不改任何设置时,一条 SQL 语句就是一个事务。
  • 若无显式控制,每条 SQL 各算各的,独立提交。

易错点:不要以为连续操作自动同事务;未显式控制就每条 SQL 独立提交,想多句绑一起必须手动开事务。

3.3 事务的必要性

  • 转账中,钱从一方划走、另一方未加上就崩溃,必须保证要么转账成功,要么回滚回原账户。
  • 单条 SQL 虽能持久化,但回滚命令可能失效,导致错误结果被定死。

重点:需主动用回滚等机制保证一致性,不能依赖单条语句自动处理,否则崩溃会造成数据错乱。

3.4 在 MySQL 中操作事务的两种方式(重点)

方式一:使用命令显式开启事务
复制代码
start transaction; -- 开启事务
update t_account set money = money - 1000 where username = '冠希';
update t_account set money = money + 1000 where username = '美美';
commit; -- 提交事务(事务已经结束,数据永久保存到数据库中)
-- 或
rollback; -- 回滚事务(事务已经结束,数据回滚到最初始化的状态)

重点:

  • 事务结束只有提交或回滚两种方式,一旦结束,start transaction 指令失效。
  • 没开事务的修改不受回滚保护,回滚只对当前未结束事务有效。
  • commit 提交后事务结束,改动落盘,此时再 rollback 毫无意义。
  • 未提交前回滚可撤销。
方式二:设置 MySQL 事务不默认提交

MySQL 数据库的事务默认是自动提交的,默认使用一个事务。设置不默认提交:

复制代码
set autocommit = off; -- 或 set autocommit = 0;

编写 SQL 语句(执行完都没有提交):

复制代码
update t_account set money = money - 1000 where username = '冠希';
update t_account set money = money + 1000 where username = '美美';

需要手动提交或回滚:

复制代码
commit;
-- 或
rollback;

查看事务是否默认提交:

复制代码
show variables like 'autocommit';

设置不默认提交后,再执行上面的两条 update,最后手动 commit 或 rollback。

易错点:

  • 不要以为执行完 SQL 就生效,必须 commit 才真正提交。
  • 不要以为没开事务也能回滚,自动提交下单行 SQL 已落库。
  • 要区分"显式事务"(start transaction)和"关闭自动提交后的隐式手动事务"(set autocommit = off)。

第四部分:JDBC 中操作事务

4.1 Connection 接口

操作事务需要掌握 Connection 接口提供的方法:

方法 作用
void setAutoCommit(boolean autoCommit) 传入 false,设置数据库事务不默认提交
void commit() 提交事务
void rollback() 回滚事务

Connection 接口的两个作用:

复制代码
操作数据库都需要使用 Connection 接口
管理事务

4.2 JDBC 控制事务的唯一方式

  • JDBC 控制事务只有一种方式:把连接对象的默认自动提交关闭,即 setAutoCommit(false)。
  • 没有 start transaction 那种写法,因为 Connection 对象只提供这个方法。
  • 之后若捕获异常就 rollback,全部执行成功再 commit。

核心流程:

复制代码
关自动提交 → 异常回滚 → 正常提交

易错点:

  • 不要以为有类似 MySQL 客户端的开启事务写法,JDBC 只有这一种方式。
  • 不要以为框架各有各的事务开关,MyBatis 及 MyBatis-Plus 也是基于 setAutoCommit(false) 实现,并非另起一套;底层统一走 JDBC 这一种机制。

第五部分:事务四大特性 ACID

特性 说明
原子性 Atomicity 事务中操作是不可再分割的原子单位,要么全部成功,要么全部失败
一致性 Consistency 事务执行后,数据库状态与其他业务规则保持一致;如转账无论成功与否,两账号余额之和不变
隔离性 Isolation 并发操作中,不同事务之间应隔离开来,使每个并发中的事务不会相互干扰
持久性 Durability 一旦事务提交成功,数据操作必须持久化到数据库;即使提交后数据库马上崩溃,重启时也必须能恢复数据

重点:

  • 原子性保整体成败。
  • 一致性保业务总额规矩不被破坏。
  • 持久性是事务结束后数据永久保留。
  • 隔离性最关键也最难理解,因涉及并发场景。

例:张三给李四转账时,王五同时给赵六转账完全允许,这是两套事务,不能让彼此产生影响,就像两条并行车道互不影响。

易错点:隔离性指并发任务各自独立、不冲突,不论是否操作同一数据。


第六部分:不考虑隔离性引发的问题

问题 定义 关键词
脏读 一个事务读取到了另一个事务未提交的数据 未提交
不可重复读 一个事务读取到了另一个事务提交的数据,导致多次查询结果不一致 update,修改记录
虚读(幻读) 一个事务读取到了另一个事务提交的数据,导致多次查询结果不一致 insert,向表中添加数据

6.1 脏读

银行柜台类比:A、B 柜台各开事务,A 柜台张冠希给美美转 1000 元但还没提交,此时 B 柜台查询却看到冠希少 1000、美美多 1000------这就是读了未提交的变更。

重点:未提交的事务结果不该被别的事务看见,否则数据不可靠。

6.2 不可重复读

两个事务同时开启,A 提交了但 B 还没结束,B 在自身未结束时读到了 A 提交的结果,破坏隔离性,叫不可重复读。

6.3 虚读/幻读

表现也是多次查询结果不一致,但针对的是另一事务的 insert 操作,比如 A 事务中 B 事务插入数据使记录数变多。

易错点:

  • 脏读对应"未提交",不可重复读对应"已提交",但都发生在多事务并发、相互干扰的场景。
  • 区分不可重复读与幻读,核心看另一事务动的是改还是增。

第七部分:事务隔离级别

7.1 四种隔离级别

隔离级别 解决的问题
Read uncommitted 什么都解决不了
Read committed 避免脏读,但不可重复读和虚读有可能产生
Repeatable read 避免脏读和不可重复读,虚读有可能产生
Serializable 避免各种读

7.2 安全性与效率

复制代码
安全性:Serializable > Repeatable read > Read committed > Read uncommitted
效率:  Serializable < Repeatable read < Read committed < Read uncommitted

重点:安全与效率互斥,越安全(约束多)效率越低,越不安全效率越高。按安全或效率取舍级别即可。

7.3 数据库默认隔离级别

数据库 默认隔离级别
Oracle Read committed(第二种)
MySQL Repeatable read(第三种),避免脏读和不可重复读

重点:

  • 第一种和第二种一般不考虑。
  • MySQL 默认第三种,虽避免幻读,但不是靠隔离级别本身,而是 InnoDB 引擎通过锁和 MVCC 版本控制实现,属 MySQL 架构内容,可先搁置。
  • 隔离级别排序:读未提交、读已提交、可重复读、串行化;RR 是 MySQL 默认可重复读,属第三档。

易错点:不要误以为"避免幻读"是隔离级别直接完成的。

7.4 隔离级别演示要点

查看当前隔离级别:

复制代码
select @@tx_isolation;

设置隔离级别(提交结束后再设):

复制代码
set session transaction isolation level read committed;
set session transaction isolation level repeatable read;
set session transaction isolation level serializable;

演示结论:

隔离级别 演示现象
第一种(读未提交) 左侧能读到右侧未提交的中间值,出现脏读;若右侧 rollback,你看到钱转走又没了
第二种(读已提交) 左侧查不到右侧未提交的变更,脏读被阻止;但右侧提交后,左侧同一事务内重查结果变化,出现不可重复读
第三种(可重复读) 未提交时无脏读;提交后左侧再查仍是原值,多次查询一致,避免不可重复读
第四种(串行化) 可避免幻读,但演示效果不好,建议搜 AI 写示例;一般不考虑该级
相关推荐
职豚求职小程序刷题1 小时前
宁德时代社招高岗晋升测评笔试改版了
笔记
见闻小天地1 小时前
新手入门:印刷包装设备的伺服和PLC运动控制方案各管什么?七步选型讲清楚
运维·网络·数据库·人工智能
鬼手点金1 小时前
KV Cache 未必是一次性的:可编辑、可组合的“笔记”
java·人工智能·笔记·学习·自动化·1024程序员节
摇滚侠1 小时前
《On Java 中文版 基础卷》阅读笔记 初始化和清理 08
java·开发语言·笔记
海鸥-w2 小时前
Redis 配置与排错说明
java·数据库·redis·bootstrap
jaysee-sjc2 小时前
【苍穹外卖】Day12:工作台数据看板与 Excel 报表导出
java·开发语言·数据库·spring boot·spring·微信·excel
sunburn-2 小时前
数据库聚合查询完整教程:从基础函数到实战统计
java·数据库·mysql·数据库开发
dire_7772 小时前
TH26027A开尔文夹子线缆问题导致同惠TH2822电桥测量不准
笔记
小蒜学长3 小时前
基于 Spring Boot 的英语单词背诵系统的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端