宁波做网站排名的公司有哪些,电子游戏十大正规官方网址,某旅行社网站建设策划书,如何自己设计装修效果图目录
开启事务
编程式事务
声明式事务
声明式事务的优点
声明式事务的粒度问题
声明式事务用不对容易失效
Spring事务失效可能是哪些原因
Transactional(rollbackFor Exception.class)注解
Spring 事务的实现原理
事务传播机制
介绍
用法
rollbackFor
场景举例 …目录
开启事务
编程式事务
声明式事务
声明式事务的优点
声明式事务的粒度问题
声明式事务用不对容易失效
Spring事务失效可能是哪些原因
Transactional(rollbackFor Exception.class)注解
Spring 事务的实现原理
事务传播机制
介绍
用法
rollbackFor
场景举例
事务接口 开启事务 事务管理在系统开发中是不可缺少的一部分Spring提供了很好的事务管理机制主要分为编程式事务和声明式事务两种 编程式事务 基于底层的API如PlatformTransactionManager、TransactionDefinition 和 TransactionTemplate 等核心接口开发者完全可以通过编程的方式来进行事务管理编程式事务方式需要开发者在代码中手动的管理事务的开启、提交、回滚等操作 如以上代码开发者可以通过API自己控制事务 声明式事务 声明式事务管理方法允许在开发者配置的帮助下来管理事务而不需要依赖底层API进行硬编码开发者可以只使用注解或基于配置的 XML 来管理事务 如上使用Transactional 即可给test方法增加事务控制 声明式事务的优点 通过上面的例子其实我们可以很容易的看出来声明式事务帮助我们节省了很多代码他会自动帮我们进行事务的开启、提交以及回滚等操作把程序员从事务管理中解放出来声明式事务管理是使用了 AOP 实现的本质就是在目标方法执行前后进行拦截在目标方法执行前加入或创建一个事务在执行方法执行后根据实际情况选择提交或是回滚事务使用这种方式对代码没有侵入性方法内只需要写业务逻辑就可以了但是声明式事务真的有这么好么倒也不见得 声明式事务的粒度问题 首先声明式事务有一个局限那就是他的最小粒度要作用在方法上也就是说如果想要给一部分代码块增加事务的话那就需要把这个部分代码块单独独立出来作为一个方法但是正是因为这个粒度问题本人并不建议过度的使用声明式事务首先因为声明式事务是通过注解的有些时候还可以通过配置实现这就会导致一个问题那就是这个事务有可能被开发者忽略事务被忽略了有什么问题呢首先如果开发者没有注意到一个方法是被事务嵌套的那么就可能会在方法中加入一些如RPC远程调用、消息发送、缓存更新、文件写入等操作我们知道这些操作如果被包在事务中有两个问题1、这些操作自身是无法回滚的这就会导致数据的不一致可能RPC调用成功了但是本地事务回滚了可是RPC调用无法回滚了2、在事务中有远程调用就会拉长整个事务那么就会导致本事务的数据库连接一直被占用那么如果类似操作过多就会导致数据库连接池耗尽有些时候即使没有在事务中进行远程操作但是有些人还是可能会不经意的进行一些内存操作如运算或者如果遇到分库分表的情况有可能不经意间进行跨库操作但是如果是编程式事务的话业务代码中就会清清楚楚看到什么地方开启事务什么地方提交什么时候回滚这样有人改这段代码的时候就会强制他考虑要加的代码是否应该在方法事务内有些人可能会说已经有了声明式事务但是写代码的人没注意这能怪谁话虽然是这么说但是我们还是希望可以通过一些机制或者规范降低这些问题发生的概率比如建议大家使用编程式事务而不是声明式事务因为有些时候声明式事务确实不够明显 声明式事务用不对容易失效 除了事务的粒度问题还有一个问题那就是声明式事务虽然看上去帮我们简化了很多代码但是一旦没用对也很容易导致事务失效如以下几种场景就可能导致声明式事务失效1、Transactional 应用在非 public 修饰的方法上2、Transactional 注解属性 propagation 设置错误3、Transactional 注解属性 rollbackFor 设置错误4、同一个类中方法调用导致Transactional 失效5、异常被catch捕获导致Transactional 失效6、数据库引擎不支持事务以上几个问题如果使用编程式事务的话很多都是可以避免的使用声明式事务失效的问题如因为Spring的事务是基于AOP实现的但是在代码中有时候我们会有很多切面不同的切面可能会来处理不同的事情多个切面之间可能会有相互影响在之前的一个项目中发现Service层的事务全都失效了一个SQL执行失败后并没有回滚排查下来才发现是因为新增了一个切面这个切面里面做个异常的统一捕获导致事务的切面没有捕获到异常导致事务无法回滚很多人还是会说说到底还是自己能力不行对事务理解不透彻用错了能怪谁但是还是那句话我们确实无法保证所有人的能力都很高也无法要求所有开发者都能不出错我们能做的就是尽量可以通过机制或者规范来避免或者降低这些问题发生的概率其实如果大家有认真看过阿里巴巴出的那份Java开发手册的话其实就能发现其中的很多规约并不是完完全全容易被人理解有些也比较生硬但是其实这些规范都是从无数个坑里爬出来的开发者们总结出来的关于Transactional 的用法规约中也有提到过只不过规约中的观点没有这么鲜明 Spring事务失效可能是哪些原因 Spring中比较容易失效的就是通过Transactional 定义的声明式事务他在以下几个场景中会导致事务失效一定要注意1、Transactional 应用在非 public 修饰的方法上 private方法只会在当前对象中的其他方法中调用也就是会进行对象的自调用这种情况是用this调用的并不会走到代理对象而Transactional 是基于动态代理实现的所以代理会失效2、Transactional 注解属性 propagation 设置错误 以上如果事务发生回滚则methodA并不会回滚因为他的propagation是不支持事务那么他就不会一起回滚3、Transactional 注解属性 rollbackFor 设置错误 以上如果发生非RuntimeException则事务不会回滚那么就会导致事务失效所以需要指定为 (rollbackFor Exception.class)4、同一个类中方法调用导致Transactional 失效 以上和private是一回事因为没办法走到代理服务所以事务会失效5、异常被catch捕获导致Transactional 失效 以为异常被捕获所以就没办法基于异常进行rollback了所以事务会失效6、数据库引擎不支持事务这个好理解如myisam不支持的肯定就不行了 Transactional(rollbackFor Exception.class)注解 Exception分为运行时异常RuntimeException和非运行时异常事务管理对于企业应用来说是至关重要的即使出现异常情况它也可以保证数据的一致性当 Transactional 注解作用于类上时该类的所有 public 方法将都具有该类型的事务属性同时我们也可以在方法级别使用该标注来覆盖类级别的定义如果类或者方法加了这个注解那么这个类里面的方法抛出异常就会回滚数据库里面的数据也会回滚在 Transactional 注解中如果不配置 rollbackFor 属性那么事物只会在遇到 RuntimeException 的时候才会回滚加上 rollbackForException.class可以让事物在遇到非运行时异常时也回滚 Spring 事务的实现原理 Spring 事务的本质其实就是数据库对事务的支持没有数据库的事务支持Spring是无法提供事务功能的真正的数据库层的事务提交和回滚是通过binlog或者 redo log 实现的编程式事务管理使用 TransactionTemplate声明式事务管理是建立在 AOP 之上的其本质是通过 AOP 功能对方法前后进行拦截将事务处理的功能编织到拦截的方法中也就是在目标方法开始之前加入一个事务在执行完目标方法之后根据执行情况提交或者回滚事务声明式事务最大的优点就是不需要在业务逻辑代码中掺杂事务管理的代码只需在配置文件中做相关的事务规则声明或通过Transactional 注解的方式便可以将事务规则应用到业务逻辑中声明式事务管理要优于编程式事务管理这正是 Spring 倡导的非侵入式的开发方式使业务代码不受污染只要加上注解就可以获得完全的事务支持唯一不足地方是最细粒度只能作用到方法级别无法做到像编程式事务那样可以作用到代码块级别 事务传播机制 介绍 Spring的事务传播机制用于控制在多个事务方法相互调用时事务的行为在复杂的业务场景中多个事务方法之间的调用可能会导致事务的不一致如出现数据丢失、重复提交等问题使用事务传播机制可以避免这些问题的发生保证事务的一致性和完整性Spring的事务规定了7种事务的传播级别默认的传播机制是REQUIRED required如果不存在事务则开启一个事务如果存在事务则加入之前的事务总是只有一个事务在执行required_new每次执行新开一个事务supported有事务则加入事务没有事务则普通执行not_supported有事务则暂停该事务没有则普通执行mandatory强制有事务没有事务则报异常never有事务则报异常nested如果之前有事务则创建嵌套事务嵌套事务回滚不影响父事务反之父事务影响嵌套事务Spring的事务隔离有五大隔离级别默认值为 ISOLATION_DEFAULT使用数据库的设置其他四个隔离级别和数据库的隔离级别一致 用法 假设有两个业务方法A和B方法A在方法B中被调用需要在事务中保证它们的一致性如果方法A或方法B中的任何一个方法发生异常则需要回滚事务使用Spring的事务传播机制可以在方法A和方法B上使用相同的事务管理器并通过设置相同的传播行为来保证事务的一致性和完整性具体实现如下 在上述示例中方法A和方法B都使用了REQUIRED的传播行为表示如果当前存在事务则在当前事务中执行如果当前没有事务则创建一个新的事务如果在方法A或方法B中出现异常则整个事务会自动回滚 rollbackFor rollbackFor是Spring事务中的一个属性用于指定哪些异常会触发事务回滚在一个事务方法中如果发生了rollbackFor属性指定的异常或其子类异常则事务会回滚如果不指定rollbackFor则默认情况下只有RuntimeException和Error会触发事务回滚 场景举例 问一个长的事务方法a在读写分离的情况下里面既有读库操作也有写库操作再调用个读库方法b方法b该用什么传播机制呢这种情况读方法如果是最后一步直接not_supported就行了避免读报错导致数据回滚如果是中间步骤最好还是要required因为异常失败需要回滚一下 事务接口 PlatformTransactionManager平台事务管理器TransactionDefinition事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)TransactionStatus事务运行状态所谓事务管理其实就是“按照给定的事务规则来执行提交或者回滚操作”PlatformTransactionManager接口介绍 Spring并不直接管理事务而是提供了多种事务管理器他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager通过这个接口Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器但是具体的实现就是各个平台自己的事情了PlatformTransactionManager接口中定义了三个方法 #getTransaction(TransactionDefinition definition)方法根据事务定义 TransactionDefinition获得 TransactionStatus 为什么不是创建事务呢因为如果当前如果已经有事务则不会进行创建一般来说会跟当前线程进行绑定如果不存在事务则进行创建#commit(TransactionStatus status)方法根据 TransactionStatus 情况提交事务 为什么根据 TransactionStatus 情况进行提交例如说带Transactional 注解的的 A方法会调用 Transactional 注解的的 B 方法在 B 方法结束调用后会执行 PlatformTransactionManager#commit(TransactionStatus status)方法此处事务是不能、也不会提交的而是在 A 方法结束调用后执行 PlatformTransactionManager#commit(TransactionStatus status)方法提交事务使用 Spring 事务通过 PlatformTransactionManager为不同的数据层持久框架提供统一的API无需关心到底是原生 JDBC、Spring JDBC、JPA、Hibernate 还是 MyBatis