一、什么是事务?
事务是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务
是一组不可再分割的操作集合(工作逻辑单元)。
事务特性:ACID
1.
原子性:事务不可分割
2.
一致性:事务执行的前后,数据完整性保持一致
3.
隔离性:一个事务执行的时候,不应该受到其他事务的打扰
4.
持久性:一旦结束,数据就永久的保存到数据库
二、Spring 事务管理实现方式有两种:编程式事务和声明式事务。
1. 编程式事务使用 TransactionTemplate 或使用底层的 PlatformTransactionManager,显式的方式调用 beginTransaction() 开启事务、commit() 提交事务、
rollback() 回滚事务,编写代码形式来声明事务。
2. 声明式事务
底层是建立在 Spring AOP 的基础上,在方式执行前后进行拦截,并在目标方
法开始执行前创建新事务或加入一个已存在事务,最后在目标方法执行完后根据
情况提交或者回滚事务。
声明式事务的优点:不需要编程,减少了代码的耦合,在配置文件中配置并在目
标方法上添加 @Transactional 注解来实现。
事务的原理:当一个方法加上@Transactional注解,spring会基于这个类生成一个代理对象并将这个代理对象作为bean,当使用这个bean中的方法时,如果存在@Transactional注解,就会将事务自动提交设为false,然后执行方法,执行过程没有异常则提交,有异常则回滚。
三、举个简单的例子
假设有一个银行账户管理的Service类,其中包含两个方法:转账方法和查询余额方法,需要保证转账操作具有原子性。代码如下:
@Service
public class AccountService {
//@Autowired注入的可以是接口、抽象类或者具体类,但一般都是注入接口,以便于实现依赖反转和松耦合的设计模式。
@Autowired
private AccountDao accountDao;
@Transactional
public void transfer(long fromAccountId, long toAccountId, double amount) {
Account fromAccount = accountDao.find(fromAccountId);
Account toAccount = accountDao.find(toAccountId);
// 转出账户扣款
fromAccount.setBalance(fromAccount.getBalance() - amount);
accountDao.update(fromAccount);
// 转入账户收款
toAccount.setBalance(toAccount.getBalance() + amount);
accountDao.update(toAccount);
}
public double getBalance(long accountId) {
return accountDao.find(accountId).getBalance();
}
}
在上述代码中,@Transactional注解被用来声明转账方法是一个事务方法。当调用转账方法时,Spring会对其进行拦截并开启一个新事务,如果整个过程没有发生异常,则提交事务。如果发生异常,则回滚事务。这样可以保证即使在转账操作期间发生异常,也能保证数据完整性,避免出现一方转账成功而另一方失败的情况。