文章目录
Spring事务
1.事务回顾
1.1什么是事务
事务指的就是数据库中多个操作合并在一起形成的操作序列
1.2 事务的作用
1.当数据库操作序列中个别操作失败时,提供一种方式使数据库状态恢复到正常状态。保障数据库即使在异常状态下仍能保持数据的一致性(要么是操作前的状态,要不是操作后的状态)。
2.当出现并发访问数据库时,在多个访问之间进行相互隔离。防止并发操作结果互相干扰。
1.3 事务的特性(ACID)
原子性A:指事务是一个不可分割的整体。其中的操作要么全部执行,要不全部不执行。
一致性C:事务前后数据的完成性必须保持一致
隔离性I:事务的隔离性就是多个用户并发访问数据库时,数据库为每个用户开启事务,不被其他事务的 操作数据所干扰。
持久性D:指得就是一个事务一旦被提交,它对数据库的改变是永久性,不可逆的。
1.4 事务的隔离级别
脏读:允许读取未提交的数据信息
解决方案:表级读锁
不可重复读:读取过程中单个数据发生了改变
解决方案:行级写锁
幻读:读取过程中数据条目发生了变化
解决方案:表级写锁
2.Spring事务
J2EE开发中使用分层的设计思想。在此分层开发中如果是简单的业务。事务开启在业务层(Service)或持久化层(Dao)并没有什么区别。但是当业务中包含了多个持久化层的调用时,需要在业务层开启事务。对持久化层中多个操作进行组合并且交由同一个事务处理。
Spring为业务层提供一套事务的解决方案:
PlatformTransactionManager:获取事务,提交事务,回滚事务
TransactionDefinition:定义了事务的基本信息。获取事务定义的名称,获取事务的读写属性,获取事务的隔离级别。获取事务的超时时间。获取事务的传播特性。
TransactionStatus:此接口定义事务在执行过程中某个时间点上事务的状态信息。
第三方技术事务管理器的实现:
适用于Spring JDBC和mybatis :DataSourceTransactionManager
3.事务控制实现
3.1 编程式事务
//创建事务管理器
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
//为事务管理器设置与持久化层相同的数据源
dstm.setDataSource(datasource);
//创建事务的定义对象
TransactionDefinition td = new DefaultTransactionDefinition();
//开启事务
TransactionStatus ts = dstm.getTransaction(td);
empMapper.outMoney(outId,money);
empMapper.inMoney(inId,money);
//提交事务
dstm.commit(ts);
由于上述代码中事务管理模块存在大量的共性代码,所以可以使用AOP(原生)进行控制事务
public void transfer(String outId,String inId,Double money) {
empMapper.outMoney(outId,money);
empMapper.inMoney(inId,money);
}
@Component
public class TxAdvice {
@Autowired
private DataSource datasource;
@Pointcut("execution(* com.lxk.service.EmpServiceImpl.transfer(..))")
public void pt() {}
@Around("pt()")
public Object tx(ProceedingJoinPoint pjp) throws Throwable {
//创建事务管理器
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
//为事务管理器设置与持久化层相同的数据源
dstm.setDataSource(datasource);
//创建事务的定义对象
TransactionDefinition td = new DefaultTransactionDefinition();
//开启事务
TransactionStatus ts = dstm.getTransaction(td);
//调用原始方法
Object proceed = pjp.proceed();
dstm.commit(ts);
return proceed;
}
}
3.2 声明式事务(XML)
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"></property>
</bean>
<tx:advice id="txadvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" read-only="false"/>
<tx:method name="find*" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut expression="execution(* *..*(..))" id="pt"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>
事务传播行为:
事务的管理员。事务的协调员。
事务的传播行为描述的就是事务的协调员对事务管理员所携带事务的态度。
1、PROPAGATION_REQUIRED:默认事务类型,如果事务管理员没有,事务协调员就新建一个事务;如果事务管理员有,就加入当前事务。
2、PROPAGATION_REQUIRES_NEW:如果事务管理员没有,事务协调员就新建一个事务;如果事务管理员有,也不使用事务管理员的事务。依然新建事务。
3、PROPAGATION_NESTED:如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。
4、PROPAGATION_SUPPORTS:如果没有,就以非事务方式执行;如果有,就使用当前事务。
5、PROPAGATION_NOT_SUPPORTED:如果没有,就以非事务方式执行;如果有,就将当前事务挂起。即无论如何不支持事务。
6、PROPAGATION_NEVER:如果没有,就以非事务方式执行;如果有,就抛出异常。
7、PROPAGATION_MANDATORY:如果没有,就抛出异常;如果有,就使用当前事务。
3.3 声明式事务(注解)
@Transactional:代表使用注解控制事务。可以定义方法上,也可以定义在类上。
tx:annotation-driven/:开启事务的注解
纯注解驱动: