1.事务怎么开启
spring事务有固定的几步:
- 初始化DataSource --- 创建DataSource类IOC注入spring
- 将DataSource交给Spring --- 创建DataSourceTranscationManager 类注入到spring
- 开启spring事务 --- @EnableTranscationManager
接下来就是关于 connection 怎么 开启和提交事务了 (核心点:事务是从connection上开启)
大多数同学使用 mybatis + spring-tx管理事务,却对spring如何处理事务一无所知,所以必须阅读源码并加上调试,搞懂其处理机制
- 使用事务:mybatis + springTx
- ORM框架:写sql,包装成mapper框架去获取当前线程对应connection 执行sql ,最后方法执行完,spring进行connection'的提交和释放
- 学习事务:jdbc-原生sql + 手动提交事务
- 直接拿到DataSource进行connection操作,设置autoCommit=false,执行写操作之后进行commit,然后手动释放connection
- 学习spring事务管理的同学:原生sql + springTx (这个就很有意思了)
- 先要了解spring事务如何实现------>被事务管理(如:@Transcation)的方法先进行AOP处理- (必然会有adviser = TranscationInterceptor ,如 TransactionAspectSupport )获取到经过增强的代理类
- 将本次事务对应的connection存放到ThreadLocal中,保证事务操作在一个DBconn 的 session中
- 手写原生sql,并且获取(DataSourceUtils / ) 到connection 执行exceute方法
- 等方法执行完成,AOP拦截会帮我们处理connection的提交和释放
2.事务什么时候会失效? / 带上失效原因
要是了解了AOP的原理和事务的实现过程,我想再问什么时候事务会失效就显得太没意思!!!
场景一:默认A、B 在用一个类中,先调用方法A,A方法直接调用方法B,方法B-先更新数据操作 ,后抛出异常
《事物级别默认是REQUEST,回滚所有异常》
No | 方法A | 方法B | DB更新情况 | 事务有效情况 |
---|---|---|---|---|
1 | 有事务 | 有事务 | 无更新 | 有效 |
2 | 有事务 | 无事务 | 无更新 | 有效 |
3 | 无事务 | 有事务 | 有更新 | 无效 |
4 | 无事务 | 无事务 | 有更新 | 无效 |
Q:为什么No.3的情况方法B 事务 不生效?
A:
- 事务是springAOP管理,通过动态代理实现
- A方法是代理类执行的方法,B方法是A方法内部调用,B方法是目标类方法调用。
图一:
图二:
Q:有没有办法:A方法不走事务,B方法走事务,A调用B,B事务生效呢?
A:当然有啦!
1.第一种:设法是B方法的调用对象是代理对象 --- 通过ApplicationContext中获取实例
2.第二种编程式事务:自己动手控制conn的提交和回滚
Q: 如果存在一种情况,
----------------------
其中spring七个事物传播属性:
PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就新建事务
----------------------
事务隔离级别与数据库相对应