app ui设计欣赏 网站wordpress小程序调用
app ui设计欣赏 网站,wordpress小程序调用,网站如何减少404跳转,上海传媒公司招聘艺人目录前言一、什么是事务#xff1f;一句话定义直观理解#xff08;转账例子#xff09;二、事务解决了什么问题#xff1f;三、事务的四大特性#xff08;ACID#xff09;四、Spring 中事务是如何实现的#xff1f;使用方式本质原理#xff08;非常重要#xff09;五、…目录前言一、什么是事务一句话定义直观理解转账例子二、事务解决了什么问题三、事务的四大特性ACID四、Spring 中事务是如何实现的使用方式本质原理非常重要五、事务应该加在哪里核心设计问题✅ 正确做法99% 场景❌ 错误做法一每个方法都加事务❌ 错误做法二apply 不加事务内部方法加六、为什么 this.xxx() 会导致事务失效1️⃣ 同一个类中的 this 调用2️⃣ 正确写法通过代理对象调用方式一从容器获取 Bean方式二推荐自注入代理对象七、同一个类 vs 不同类调用事务方法1️⃣ 同一个类中2️⃣ 不同类中推荐结构八、事务方法内部能不能用 this 调用其他方法✅ 可以而且是正确的⚠️ 前提条件九、什么时候内部方法也要加 Transactional示例日志必须单独提交十、使用事务时必须注意的 6 个坑十一、实战如何实现“全成功或全回滚”十二、总结前言在 Spring Boot 项目中事务是保证数据一致性的核心机制之一。但同时它也是**最容易“看起来写了其实没生效”**的功能。本文将围绕以下问题展开什么是事务解决什么问题Transactional到底是怎么生效的事务应该加在“哪里”才是对的为什么this.xxx()会导致事务失效同一个类、不同类调用事务方法的区别真实项目中事务的最佳实践一、什么是事务一句话定义事务是一组操作要么全部成功要么全部失败回滚。直观理解转账例子转账操作至少包含两步A 账户扣钱B 账户加钱这两个操作不能只成功一个必须作为一个整体成功或失败这就是事务存在的意义。二、事务解决了什么问题事务主要解决三类核心问题问题没事务会发生什么数据一致性只成功一半异常回滚出错后数据已落库并发安全并发修改产生脏数据三、事务的四大特性ACID这是原理但理解比背更重要。A原子性要么全成功要么全失败C一致性事务前后数据状态合法I隔离性并发事务互不干扰D持久性提交后数据不会丢失四、Spring 中事务是如何实现的使用方式Spring 中最常见的事务用法TransactionalpublicvoiddoBusiness(){// 数据库操作}本质原理非常重要Spring 的事务是通过 AOP 代理对象实现的执行流程大致是调用代理对象方法方法执行前 → 开启事务方法正常结束 → 提交事务方法抛异常 → 回滚事务关键前提必须是通过“代理对象”调用方法。五、事务应该加在哪里核心设计问题假设你有如下业务publicvoidapply(Commandcommand){queryData();deleteData();saveData();commitData();}目标是apply 方法里的所有数据库操作要么全成功要么全回滚✅ 正确做法99% 场景Transactional(rollbackForException.class)publicvoidapply(Commandcommand){queryData();deleteData();saveData();commitData();}只在“业务入口方法”上加事务。❌ 错误做法一每个方法都加事务TransactionalpublicvoidqueryData(){}TransactionalpublicvoidsaveData(){}问题事务边界被拆碎业务完整性不清晰维护成本高❌ 错误做法二apply 不加事务内部方法加publicvoidapply(){saveData();// 提交commitData();// 抛异常}结果前面的数据已经提交无法整体回滚六、为什么this.xxx()会导致事务失效这是 Spring 事务最经典的坑。1️⃣ 同一个类中的 this 调用publicvoidaa(){this.apply();// ❌}Transactionalpublicvoidapply(){}事务不会生效。原因this调用绕过了 Spring 代理AOP 无法介入Spring 的事务是基于 AOP面向切面编程 实现的。当你为一个方法加上 Transactional 时Spring 会生成一个 代理对象Proxy。外部调用当其他类调用 apply 时实际上调用的是代理对象代理对象会先开启事务再执行业务逻辑。内部调用this如果你在类内部直接 this.apply()由于 this 指向的是原始对象而不是代理对象Spring 根本没机会介入。结果就是事务失效。2️⃣ 正确写法通过代理对象调用方式一从容器获取 BeanapplicationContext.getBean(this.getClass()).apply(command);applicationContext.getBean(this.getClass()).apply(command)的目的就是强制从 Spring 容器中获取当前类的代理对象确保调用路径经过 Spring 的拦截器从而让事务生效。方式二推荐自注入代理对象AutowiredprivateApplyServiceself;publicvoidaa(){self.apply();}七、同一个类 vs 不同类调用事务方法1️⃣ 同一个类中publicvoidaa(){this.apply();// ❌} 必须通过代理对象调用applicationContext.getBean(this.getClass()).apply()或者self.apply()2️⃣ 不同类中推荐结构ServicepublicclassAService{AutowiredprivateBServicebService;publicvoidaa(){bService.apply();}}ServicepublicclassBService{Transactionalpublicvoidapply(){}}事务天然生效八、事务方法内部能不能用 this 调用其他方法✅ 可以而且是正确的Transactionalpublicvoidapply(){this.queryData();this.saveData();}原因事务已经在apply()入口开启内部方法共享同一个事务⚠️ 前提条件内部方法没有单独的事务语义也就是说publicvoidsaveData(){}而不是TransactionalpublicvoidsaveData(){}// ⚠️九、什么时候内部方法也要加 Transactional只有在明确的事务语义不同时才需要。示例日志必须单独提交Transactionalpublicvoidapply(){saveMainData();logService.saveLog();// 即使 apply 失败也要保存thrownewRuntimeException();}Transactional(propagationREQUIRES_NEW)publicvoidsaveLog(){}十、使用事务时必须注意的 6 个坑❌ 同一类中使用this.xxx()调用事务方法❌ 异常被 try-catch 吃掉❌ 默认不回滚Exception❌Transactional加在private方法❌ 事务中开启新线程❌ 数据库引擎不支持事务如 MyISAM十一、实战如何实现“全成功或全回滚”假设你有一个 apply 方法内部包含多个数据库操作ServicepublicclassApplyService{AutowiredprivateApplyServiceself;publicvoidaa(Commandcommand){self.apply(command);}Transactional(rollbackForException.class)// 在入口方法加注解publicvoidapply(Commandcommand){// 操作1直接写 SQLuserMapper.delete(...);userMapper.insert(...);// 操作2调用类内部的其他方法,这些子方法会运行在 apply 开启的同一个事务中this.queryData();this.deleteData();this.saveData();this.commitData();}privatevoidqueryData(){}privatevoiddeleteData(){}privatevoidsaveData(){}privatevoidcommitData(){}}结论入口最重要只要 apply 是通过代理对象调用的事务就会开启。内部方法用 this 没问题一旦事务开启该线程就已经绑定了数据库连接。apply 内部通过 this 调用 saveData这些操作都会自动加入到 apply 的事务中。不要在子方法上乱加注解除非你需要特殊的传播机制比如无论如何都要记录日志否则子方法不需要重复加 Transactional。十二、总结事务应该定义在“业务入口方法”上必须通过 Spring 代理对象调用一旦进入事务方法内部普通方法直接调用即可。