概述:一件事情有n个组成单元 要不这n个组成单元同时成功 要不n个单元就同时失败,就是将n个组成单元放到一起就是一个事务(同时成功或同时失败)
- 查询没有事务,因为查询不需要回滚
事务的ACID特性
对一组SQL语句操作构成事务,数据库操作系统必须确保这些操作的原子性,一致性,隔离性,持久性
- 原子性(Atomicity)
每个事务都是一个整体,不可再拆分,事务中所有的 SQL 语句要么都执行成功, 要么都失败
-
一致性(Consistency)
事务的一致性是指数据库在事务操作前和事务处理后,其中数据必须满足业务的规则约束。如:转账前2个人的总金额是 2000,转账后 2 个人总金额也是 2000
-
隔离性(Isolation)
事务与事务之间不应该相互影响,执行时保持隔离的状态(互不影响)
- 持久性(durability)
一旦事务执行成功,对数据库的修改是持久的
事务原理
事务开启之后, 所有的操作都会临时保存到事务日志中, 事务日志只有在得到 commit 命令才会同步到数据表 中,其他任何情况都会清空事务日志(rollback,断开连接)
事务的步骤:
-
客户端连接数据库服务器,创建连接时创建此用户临时日志文件
-
开启事务以后,所有的操作都会先写入到临时日志文件中
-
所有的查询操作从表中查询,但会经过日志文件加工后才返回
-
如果事务提交则将日志文件中的数据写到表中,否则清空日志文件。
说明 | |
---|---|
conn.setAutoComnmit(false) | 关闭自动事务提交 |
commit | 提交事务 |
conn.rollback() | 回滚事务 |
注意事项
- 控制事务的connection必须是同一个
- 关闭connection的资源,会自动提交
demo
基础实现
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.junit.Test;
import cn.szsxt.demo02.JdbcUtils;
public class Demo {
@Test
public void demo02() {
// executeUpdate 自动提交事务
Connection conn = JdbcUtils.getConn();
String sql = "insert into t_stu(id,name,age) values (?,?,?)";
PreparedStatement ps = null;
try {
// 手动设置事务 把自动提交事务 给关闭
conn.setAutoCommit(false);
ps = conn.prepareStatement(sql);
// 设置参数
ps.setInt(1, 4);
ps.setString(2, "范瑶");
ps.setInt(3, 48);
// executeUpdate 自动提交事务 会把数据添加到 数据库中
int update = ps.executeUpdate();
int a = 1 / 0; // 算术异常 catch是 sqlException 不能捕获到
// 不会进入到 catch代码中 回滚不会执行 ( 一定 catch 异常的捕获 )
// 提交事务
conn.commit();
System.out.println("事务提交 ...");
if (update > 0) {
System.out.println("添加成功");
}
} catch (Exception e) {
e.printStackTrace();
// 事务回滚
if (conn != null) {
try {
// 回滚到 开始 手动提交事务 的 位置
System.out.println("事务回滚了 ");
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
} finally {
// 设置 我们的 conn 关闭的时候 自动提交事务
JdbcUtils.close(conn, ps);
}
}
}