招商网站建设费用价格,腾讯云服务器使用教程,注册人力资源公司需要什么手续,怎么制作游戏修改器作者简介#xff1a;☕️大家好#xff0c;我是Aomsir#xff0c;一个爱折腾的开发者#xff01; 个人主页#xff1a;Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏-CSDN博客 当前专栏#xff1a;Spring5应用专栏_Aomsir的博客-CSDN博客 文章目录 参考文献前言事务… 作者简介☕️大家好我是Aomsir一个爱折腾的开发者 个人主页Aomsir_Spring5应用专栏,Netty应用专栏,RPC应用专栏-CSDN博客 当前专栏Spring5应用专栏_Aomsir的博客-CSDN博客 文章目录 参考文献前言事务属性什么是事物属性如何添加事务属性 隔离属性脏读解决方案 不可重复读解决方案 幻影读解决方案 注意事项 传播属性解决方案 只读属性超时属性异常属性总结 参考文献 孙哥suns说Spring5学不会Spring? 因为你没找对人~孙帅Spring官方文档 前言
在前两篇文章中我们深入探索了Spring与MyBatis的整合技术并详细讨论了Spring在事务处理方面的能力。今天我决定进一步深入研究Spring在事务属性上进一步的深入研究
事务属性
什么是事物属性
事务属性是用来描述事务特性的一组值。主要包括隔离属性、传播属性、只读属性、超时属性和异常属性。通过这些属性我们可以全面地描述和管理事务的行为
如何添加事务属性
在上一篇文章中我们已经探讨了如何在原始方法的类或方法上使用Transaction注解来定义事务的切入点。要设置事务属性我们只需在这一注解中配置相应的属性值。例如isolation用于指定隔离级别propagation表示传播行为readOnly标识该事务是否为只读rollbackFor定义哪些异常会触发事务回滚而timeOut指定事务的超时时间。接下来我们会详细解析每一个属性的具体值和含义以帮助大家更深入地理解和使用事务属性
隔离属性
隔离属性主要描述了事务如何解决数据库事务并发操作中的问题。在此之前我们首先要明确什么是并发以及并发中可能会遇到哪些问题以及如何解决这些问题。
什么是并发 并发是指多个事务在同一时刻对相同的数据进行访问和操作。
并发会产生哪些问题 并发操作中可能出现的问题包括脏读、不可重复读和幻影读。
并发问题如何解决 并发中的问题可以通过设定合适的隔离属性来解决。根据隔离属性的不同值我们可以有效地避免或解决在并发处理过程中出现的这些问题
脏读
所谓脏读是指一个事务读取到了另一个事务尚未提交的数据这种操作可能导致当前事务中的数据不一致。想象一个场景如果事务的隔离级别设置得不够高它可能会读取到另一事务已修改但尚未提交的数据。如果在此基础上我们对这份数据进行了进一步的修改、添加或删除而后来那个外部事务决定回滚那么当前事务所做的所有操作都可能变得无效或导致数据错误
解决方案
为了避免脏读可以将事务的隔离属性设置为“读已提交”。这样事务只能读取其他事务已经提交的数据从而确保数据的一致性。在代码中这可以通过以下注解属性来实现
Transaction(isolationIsolation.READ_COMMITTED)不可重复读
所谓不可重复读是指在同一个事务内多次读取相同数据时得到的结果不同。举个例子假设在事务A中第一次查询某数据得到的结果是1000。而在事务A的两次查询之间另外一个事务B将这个数据减少了200。当事务A再次查询时得到的结果就变成了800从而导致事务A中出现了数据不一致的情况
解决方案
为了避免不可重复读的问题我们可以将事务的隔离属性设置为“可重复读”。这样的设置确保在事务执行过程中对同一数据的多次读取都能获得一致的结果。在代码中可以通过以下注解属性来实现
其本质是为相关数据加上行锁确保在当前事务执行期间其他事务不能修改这部分数据
Transaction(isolationIsolation.REPEATABLE_READ)幻影读
所谓幻影读是指在同一个事务中对整张表进行多次统计查询时得到的结果各不相同从而在事务内产生数据不一致的问题
解决方案
为了避免幻影读的问题我们可以将事务的隔离属性设置为“串行化”SERIALIZABLE。这样的设置可以确保在事务执行过程中对整张表的多次统计查询都能获得一致的结果。在代码中可以通过以下注解来实现
其核心机制是为整张表加上表锁确保在当前事务执行期间其他事务不能对此表进行添加或删除操作。
Transaction(isolationIsolation.SERIALIZABLE)注意事项
数据库默认隔离级别 Spring提供的事务属性默认值会根据不同类型的数据库的默认隔离级别进行动态选择。灵活选择隔离属性 在实际应用中我们应当灵活地选择隔离属性。根据具体的业务需求选择合适的隔离属性当然默认的设置通常也是推荐的。解决并发问题 在实战中遇到并发问题时常用的解决方法是采用悲观锁。例如可以使用JPA的Version或者通过MyBatis的拦截器进行自定义开发
传播属性
传播属性主要描述了如何解决事务嵌套的问题。事务嵌套发生在一个主事务中包含多个子事务的情况。
例如当AService中的a方法启动一个事务时这个a方法可能会调用BService的b方法和CService的c方法这两个方法都各自拥有独立的事务这种情况下就构成了事务嵌套。这样的嵌套可能导致各个子事务之间相互影响进而使主事务失去其原子性。
通过正确地设置传播属性我们可以确保在整个操作过程中只存在一个统一的事务。
解决方案
当我们需要设定事务的传播行为可以在事务注解中添加propagation属性。各个传播属性的具体值及其含义可以参考下表。
在实际开发中REQUIRED和SUPPORTS这两个传播属性可以解决99%的场景需求。
默认的传播属性是REQUIRED因此对于增、删、改的方法我们通常不需要手动设置。而对于查询方法我们则需要手动将其传播属性设置为SUPPORTS
只读属性
对于仅涉及查询操作的业务方法我们可以添加只读属性从而优化运行效率。这可以通过readOnly属性来实现。虽然它的默认值是false但在需要的时候我们可以手动开启它使查询操作更加高效
超时属性
超时属性定义了事务执行的最长允许时间。这在某些场景下尤为关键例如当当前事务所需的数据被另一个事务或代码锁定时本事务可能需要等待并尝试加锁。 我们可以通过timeout属性来设置超时限制其单位为秒。设定超时属性后为了验证其效果我们可以在业务方法中插入线程休眠代码来进行模拟和测试
异常属性
异常属性指定了在事务中发生何种异常时应执行回滚操作以及在哪些异常下应提交数据。我们可以通过属性rollbackFor和noRollbackFor来进行设置。
在Spring的事务管理中异常属性的默认设置是
当事务中发生RuntimeException及其子类的异常时系统会自动进行回滚当事务中发生Exception及其子类的异常时则默认执行提交操作。
对于大多数实际场景建议沿用此默认值尤其是对于RuntimeException及其子类
总结
经过上述详细的探讨我们对Spring事务中的各项属性有了深入的了解。现在我们来做一个简明扼要的总结
隔离属性推荐使用默认值。传播属性对于增删改操作建议直接使用默认值即REQUIRED。而对于查询操作应手动设置为SUPPORTS。只读属性对于增删改操作使用默认值即false对于查询操作应手动设置为true。超时属性根据具体业务需求来决定但默认值为-1。异常属性建议使用默认设 因此总结如下
对于增删改操作Transaction对于查询操作Transaction(propagationPropagation.SUPPORTS, readOnlytrue)