在项目中遇到的一些关于事务的问题,然后经过查阅资料,再对事务做一些分析和总结。
关于Spring事务,事务分两种:
1、编程式事务
2、声明式事务(应用注解的方式来使用事务,注解为:@Transactional)
先说明,什么是事务(MYSQL): MySQL每执行一条SQL语句,都是一个单独的事务。如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。 要么成功,要么失败,其实有涉及到事务的特性,
即: 事务必须满足四个特性:
原子性:一组事务,要么成功,要么撤回
一致性:事务执行后,数据库状态与其他 业务规则保持一致性。
隔离性:事务独立运行。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。
持久性(Durability):软、硬件崩溃后,InnoDB数据表驱动会利用日志文件重构修改
关于编程式事务:
在strust2中,公司项目工程里面,代码都是直接封装好的jar包,所以,一直都没能好好观察项目中的事务是怎么操作的。先从外部代码进行分析,其实最后都是大同小异。 从最外面一层开始看:
获取数据源,dataSource,开启连接,
开启事务用的是TransactionSynchronizer,事务获取连接,同时自动提交设置为关闭,这是公司内部框架封装好的集成,所以大概猜测功能也和Transaction注解一样,开启事务功能
获取数据库连接:
这里讲一下try catch finally ,程序执行的时候,try是一定会执行,当try执行的时候有错误的时候,执行catch语句,并抛出异常信息,再执行finally语句,
如果connection是自己新开的,需要在这个finally里面关闭connection,点击进入关闭方法,方法里面帮我们这个connection事务做了提交
在默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。
conn.commit(); //提交事务, conn.rollback();//回滚事务,
以上为公司提交事务的时候,所需要用的方法和整个流程,个人认为,和编程式事务,有点类似,不像声明式事务直接注解,自动开启事务。
回想起以前做的项目,发现自己从来都没有写过关于事务的注解,没用过编程式事务,也没有用过注解式事务。
事务一般都加在service层,但是在项目中没有找到Transctional注解,后来查资料才得知,其实事务和能不能保存数据没有关系。
开启事务只是说这个保存操作要手动commit以后才会持久化到数据库,没有手动commit以前,可以rollback。 未开启事务是说只要一做save操作,数据立马持久化到数据库。
那么问题来了,当没有开始事务的时候,Mysql插入数据库,如果中途出错了,会怎么样?这时候事务的特性就显现了,“事务是用来确保你插入的原子性的,不是用来确保成功率的。”事务的原子性,要么成功要么失败。所以当插入的时候失败了,那么这条记录插入不成功。
开启事务支持,保持数据的一致性。
好的,了解完这个,继续深入了解编程式事务。 首先获取TransactionTemplate 的核心方法
在通过实现此核心方法去实现和调用这个方法
比如:
使用1、直接new一个transactionCallback,然后再里面编程,在核心代码方法会自动帮忙提交,
使用2、new出来以后直接调用方法
这么看,编程式事务,其实挺麻烦的。
声明式事务: 先在application.xml文件中配置,这个是基于Java,SSM框架配置扫描。
然后再service层对需要进行实物控制的方法加上注解@Transactional
以上为xml版本的注解
现在来介绍关于springboot自动化注解
- @EnableTransactionManagement注解通过导入方式,在容器中注册了两个重要组件: AutoProxyRegistrar——相当于一个自定义组件注册器,在容器中注册了一个后置处理器; ProxyTransactionManagementConfiguration——是一个容器配置类,在其中注册了事务增强器。 点进@EnableTransactionManagement注解内部, @Import中的那个类,实现了ImportsSelector接口,正是通过这个ImportSelector导入了上述两个组件。
再进入TransactionManagementConfigurationSelector时候,构造了 AutoProxyRegistrar——相当于一个自定义组件注册器,在容器中注册了一个后置处理器; ProxyTransactionManagementConfiguration——是一个容器配置类,在其中注册了事务增强器。
这两个组件的实现原理,有点难。抱歉,实在怼不动,以上两个组件原理本人参考 www.cnblogs.com/dubhlinn/p/… 有兴趣的盆友可以亲自去看看 看下关于原理的总结,
- 在容器配置类上使用@EnableTransactionManagement注解,该注解在容器中注册了两大组件——AutoProxyRegistrar、ProxyTransactionManagementConfiguration;
- AutoProxyRegistrar通过导入方式在容器中注册了InfrastructureAdvisorAutoProxyCreator,这是一个后置处理器;
- ProxyTransactionManagementConfiguration本身就是一个容器配置类,它注册了transactionAdvisor(事务增强器),然后又在这个事务增强器中注入了两个属性transactionAttributeSource、transactionInterceptor;
- transactionAttributeSource用于解析@Transactional注解的各种属性;
- transactionInterceptor实现了MethodInterceptor,是一个拦截器链,这个拦截器链会从容器中获取事务管理器,利用事务管理器,在目标方法发生异常时执行回滚,在目标发生正常完成后提交事务;
- 第2步的InfrastructureAdvisorAutoProxyCreator后置处理器,会在目标对象创建完成之后将其包装为代理对象,代理对象在执行目标方法时会首先获取拦截器链,这个拦截器链就是第5步的transactionInterceptor。
还是看下怎么用吧, 利用config过滤器建立关于数据库连接, 开启事务,
然后用法同配置xml方式一致,只需在方法外加上注解即可,