Spring的事务管理
事务是什么?
事务:指单个逻辑操作单元的集合
在操作数据库时(增删改),如果同时操作多次数据,我们从业务希望,要不全部成功,要不全部失败。这种情况称为事务处理。
A转账给B。
第一步,扣除A君账号要转的金额
第二步,增加B君账号的金额
Spring事务控制我们要明确的
1.JavaEE体系进行分层开发,事务处理位于业务层,所以,一般情况下我们使用事务代理(事务管理器),一般放在分层设计业务层。
2.spring框架为我们提供了一组事务控制的应用程序接口(API)。
3.spring的事务控制都是基于AOP的,它既可以使用编程的方式实现,也可以使用配置的方式实现。我们学习的重点是使用配置的方式实现。
案例引出问题
需求:从ID为10086账户给ID为10010账户转账1000元钱。
数据准备:account表(账户):
-------------------------
ID BALANCE
-------------------------
10010 0
10086 1000
设计一个 Account表
CREATE TABLE `t_account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`balance` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10087 DEFAULT CHARSET=utf8;
编写转账案例
转账案例分析
AccountDaoImpl.java
package cn.xc.spring.dao.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import cn.xc.spring.dao.AccountDao;
@Repository
public class AccountDaoImpl implements AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void transOut(Integer outId, Integer money) {
String sql = "update t_account set balance = balance - ? where id = ?";
jdbcTemplate.update(sql, money, outId);
}
@Override
public void transIn(Integer inId, Integer money) {
String sql = "update t_account set balance = balance + ? where id = ?";
jdbcTemplate.update(sql, money, inId);
}
}
package cn.xc.spring.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.xc.spring.dao.AccountDao;
import cn.xc.spring.service.AccountService;
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Override
public void trans(Integer outId, Integer inId, Integer money) {
// 1.扣钱
accountDao.transOut(outId, money);
//System.out.println(1/0);//模拟断电
// 2.打钱
accountDao.transIn(inId, money);
}
}
结论: 根据上述案例分析, 事务管理应该是在Service层处理
数据库并发问题
什么是数据库并发问题?
并发: 多个客户端同时同时访问数据库中某一条数据(秒杀)
数据库可以拥有多个访问客户端,若多个客户端并发地访问数据库中相同的资源,如果没有采取必要的隔离措施,则会导致各种并发问题,破坏数据的完整性。
这些问题归结为5类
包括3类数据读问题(脏读,不可重复读,幻读)
和2类数据更新问题(第一类丢失更新,第二类丢失更新)。 看图
第一类丢失更新
两个事务更新相同数据,如果一个事务提交,另一个事务回滚,第一个事务的更新会被回滚
第二类丢失更新
多个事务同时读取相同数据,并完成各自的事务提交,导致最后一个事务提交会覆盖前面所有事务对数据的改变
脏读
第二个事务查询到第一个事务未提交的更新数据,第二个事务根据该数据执行,但第一个事务回滚,第二个事务操作脏数据
幻读
一个事务查询到了另一个事务已经提交的新数据,导致多次查询数据不一致
不可重复读
一个事务查询到另一个事务已经修改的数据,导致多次查询数据不一致