1 事务
1-1 事务的问题
当多个操作想要联合执行,但是中间出现了问题,导致中断,有操作没有执行完毕。可能会造成数据不正确。
1-2 事务是什么
一组逻辑操作单元,使数据从一种状态变换成另一种状态。
1-3 JDBC事务处理
-
DML:DML是Data Manipulation Language的缩写,意思是数据操纵语言,是指在SQL语言中,负责对数据库对象运行数据访问工作的指令集,以INSERT、UPDATE、DELETE三种指令为核心,分别代表插入、更新与删除,是开发以数据为中心的应用程序必定会使用到的指令。
-
DDL:全称“Data Definition Language”代表“数据定义语言”。DDL是一种用于定义数据结构和修改数据的语言,例如,DDL命令可用于添加、删除或修改数据库中的表。
-
DML(data manipulation language):它们是SELECT、UPDATE、INSERT、DELETE,就象它的名字一样,这4条命令是用来对数据库里的数据进行操作的语言。
-
DDL(data definition language):DDL比DML要多,主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定义或改变表(TABLE)的结构,数据类型,表之间的链接和约束等初始化工作上,他们大多在建立表时使用。
- 数据一旦提交,不可回滚。
- 数据什么时候意味着提交?
- DDL操作:一旦执行自动提交。
- DML操作:默认情况下,一旦执行自动提交,我们可以通过set autocommit = false 的方式取消DML操作的自动提交。
- 默认再关闭连接时,自动提交数据。
1-4 案例分析
1-4-1 未数据库考虑事务的转账操作
/* 伪代码:
1 update操作(提交了)
2 模拟网络异常(数据不正确了)
2 update操作
4 关闭资源
*/
1-4-2 考虑数据库事务的转账操作
/* 伪代码:
获取连接(此时这个连接要用参数传进来)
取消数据的自动提交功能
conn.setAotoCommit(false);
1 update操作(减钱)(不提交)
2 模拟网络异常
3 update操作(加钱)(不提交)
4 关闭资源
中间如果有异常,就catch回滚。
*/
当使用数据库连接池时:
finally{
// 修改为 自动提交
conn.setAutoCommit(true);
}
1-5 事务的ACID属性
- 原子性(Atomicity):
事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 - 一致性(Consistency):
事务必须是数据库从一个一致性状态变成另外一个一致性状态。 - 隔离性(Isolation):
并发执行的各个事务之间不互相干扰。 - 持久性(Durability):
一个事务一旦被提交,对数据库中数据的改变是永久性的,接下来的其他操作和数据库的故障不应该对其有任何影响。
1-6 数据库的3个并发问题
问题 | 描述 |
---|---|
脏读 | T1读了已经被T2修改但没有提交的数据 |
不可重复读 | 两个事务,T1读了一个字段,T2修改了这个字段,T1再读和之前那不一样 |
幻读 | 两个事务,T1读了一个字段,然后T2正在表中插入了行,之后,T1再次读同一个表。会多出很多行。 |
1-7 数据库的4种隔离机制
隔离机制 | 英文 | 实现效果 |
---|---|---|
读未提交 | READ UNCOMMITED | 解决了脏读问题 |
读已提交 | READ COMMITED | 解决了脏读问题 |
可重复读 | REPEATABLE READ | 在一个事务中,两次读保证结果是相同的。 解决了脏读、不可重复读的问题。 |
串行化 | SERIALIZABLE | 解决了解决了脏读、不可重复读、幻读的问题 |
1-8 其他
- 浏览器关了重新连接,才能更新数据 。
- Oracle支持两种事务隔离级别,READ COMMITED和SERIALIZABLE,默认的是READ COMMITED。
- MySQL支持四种事务隔离级别,MySQL默认的是REPEATABLE READ。所以并发性差一些。
- 越往下隔离性越高,并发性越差,一致性越好。
1-9 Java代码层面设置当前数据库的隔离级别
// 读已提交-避免脏读
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
数据库服务重新启动就会变回mysql默认的事务隔离级别——可重复读。
2 操作数据表的BaseDAO
- 通用的增删改操作(考虑上事务)——连接作为参数传进来,可能有好几个增删改,构成一个事务
- PrepareStatement实现针对于不同表的查询操作(考虑事务)
- PrepareStatement实现针对于不同表的查询操作
- // 查询特殊值的通用方法
/*
封装了针对数据表的通用操作
*/
public abstract class BaseDAO<T> {
private Class<T> clazz = null;
{
Type genericSuperclass = this.getClass().getGenericSuperclass();
ParameterizedType paramType = (ParameterizedType) genericSuperclass;
Type[