一,Spring事务
事务作用:在数据层保障一系列的数据库操作同成功同失败 Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败
Spring事务通过接口:
public interface PlatFormTransactionManager{
void commit(TransactionStatus stauts) throws TransactionException;
void rollback(TransactionStatus stauts) throws TransactionException;
}
它提供了一个最基础的实现类
public void DataSourceTransactionManager{
}
这个实现类内部用的是JDBC的事务,mybatis内部用的也是JDBC的事务。
快速入门:
-
在业务层接口上添加Spring事务管理
public interface AccountService{ @Transactional public void transfer(String out,String in,Double money); }注意:
- Spring注解式事务通常添加在业务层接口中而不会添加到业务层实现类中,降低耦合
- 注解式事务可以添加到业务方法上表示当前方法开启事务,也可以添加到接口上表示当前接口所有方法开启事务
-
注册事务管理器
@Configuration public class JdbcConfig{ @Bean public PlatFormTransactionManager transactionManager(DataSource datasource){ DataSourceTransactionManager ptm=new DataSourceTransactionManager(); ptm.setDataSource(datasource); } }事务管理器要根据实现技术进行选择,MyBatis框架使用的是JDBC事务,故我们SSM一般就是注册JDBC事务。
-
开启注解方式事务驱动
@EnableTransactionManagement @Configuration public class SpringConfig { }如果是基于SpringBoot开发那么不需要操作2,3两步,直接添加注解即可
二,Spring事务角色
事务角色
- 事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法
- 事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法
默认情况下,我们业务层两个执行的方法属于两个单独的事务:
在加入注解后:
三,@Transactional注解
三,事务属性
3.1 事务的回滚
3.2 事务的传播行为
常见的事务传播行为:
required:
- 假设A有事务,则B就加入A的事务。
- 假设A没有事务,则B就创建一个新的事务。
- 大部分情况下都是用该传播行为即可。
requires_new:
-
无论A有没有事务,B都会创建一个新的事务。
-
当我们不希望事务之间相互影响时,可以使用该传播行为。
比如:下订单前需要记录日志,不论订单保存成功与否,都需要保证日志记录能够记录成功。
supports:
- 假A有事务,那么事务B就加入A的事务
- 假设A没有事务,那么B也不存在事务
not_supported:
- 假设A有事务,那么A会在执行B的时候挂起,等待b执行完毕再继续运行事务
- 假设A没有事务,那么a,b在无事务的状态下执行。
3.3 事务的隔离级别
isolation 属性用于指定事务的隔离级别,它定义了一个事务与其他事务相互隔离的程度。隔离级别可以影响事务的并发性和一致性。不同的隔离级别会影响数据库在处理并发事务时的行为,从而决定事务是否会遇到**脏读(Dirty Read)、不可重复读(Non-repeatable Read)和幻读(Phantom Read)**等问题。
常见事务隔离级别:
-
Isolation.DEFAULT-
描述: 使用底层数据库的默认隔离级别。每个数据库管理系统(DBMS)都有自己的默认隔离级别,通常是
READ_COMMITTED。 -
适用场景: 当不确定应用程序具体需要哪种隔离级别时,或者希望使用数据库的默认行为。
-
-
Isolation.READ_UNCOMMITTED- 描述: 允许一个事务读取另一个事务尚未提交的数据(脏读)。可能会出现脏读、不可重复读和幻读。
- 适用场景: 在数据一致性要求不高但需要高并发性能的场景下使用。例如:临时统计分析。
-
Isolation.READ_COMMITTED- 描述: 一个事务只能读取另一个事务已经提交的数据。避免了脏读,但可能会出现不可重复读和幻读。
- 适用场景: 大多数应用程序,特别是需要避免脏读的场景。例如:大多数在线事务处理系统(OLTP)。
-
Isolation.REPEATABLE_READ- 描述: 确保在同一个事务内多次读取同样的数据结果是一致的(避免不可重复读)。可能会出现幻读。
- 适用场景: 需要在事务中多次读取相同数据且需要一致性的场景。例如:银行账户转账。
-
Isolation.SERIALIZABLE- 描述: 提供严格的事务隔离,确保事务按顺序执行。避免脏读、不可重复读和幻读,但会导致性能显著下降,因而并发性最低。
- 适用场景: 数据一致性要求极高且并发性要求较低的场景。例如:金融交易系统。
3.4 事务失效情况
-
@Transactional 应用在非 public 修饰的方法上
-
@Transactional 注解属性 propagation 设置错误
-
@Transactional 注解属性 rollbackFor 设置错误
-
同一个类中方法调用,导致@Transactional失效
开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但**方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。**这也是经常犯错误的一个地方。