范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

spring事务失效的几种场景以及原因

  前言
  spring事务失效场景可能大家在很多文章都看过了,所以今天就水一篇,看大家能不能收获一些不一样的东西。直接进入主题 spring事务失效场景以及原因1、场景一:service没有托管给springpublic class TranInvalidCaseWithoutInjectSpring {      private UserService userService;      public TranInvalidCaseWithoutInjectSpring(UserService userService) {         this.userService = userService;     }      @Transactional     public boolean add(User user){         boolean isSuccess = userService.save(user);         int i = 1 % 0;         return isSuccess;     } }     @Test     public void testServiceWithoutInjectSpring(){         boolean randomBoolean = new Random().nextBoolean();         TranInvalidCaseWithoutInjectSpring tranInvalidCaseWithoutInjectSpring;         if(randomBoolean){             tranInvalidCaseWithoutInjectSpring = applicationContext.getBean(TranInvalidCaseWithoutInjectSpring.class);             System.out.println("service已经被spring托管");         }else{             tranInvalidCaseWithoutInjectSpring = new TranInvalidCaseWithoutInjectSpring(userService);             System.out.println("service没被spring托管");         }          boolean isSuccess = tranInvalidCaseWithoutInjectSpring.add(user);         Assert.assertTrue(isSuccess);      }
  失效原因:  spring事务生效的前提是,service必须是一个bean对象
  解决方案:  将service注入spring 2、场景二:抛出受检异常@Service public class TranInvalidCaseByThrowCheckException {      @Autowired     private UserService userService;       @Transactional     public boolean add(User user) throws FileNotFoundException {         boolean isSuccess = userService.save(user);         new FileInputStream("1.txt");         return isSuccess;     }     }   @Test     public void testThrowCheckException() throws Exception{         boolean randomBoolean = new Random().nextBoolean();         boolean isSuccess = false;         TranInvalidCaseByThrowCheckException tranInvalidCaseByThrowCheckException = applicationContext.getBean(TranInvalidCaseByThrowCheckException.class);         if(randomBoolean){             System.out.println("配置@Transactional(rollbackFor = Exception.class)");             isSuccess = tranInvalidCaseByThrowCheckException.save(user);         }else{             System.out.println("配置@Transactional");             tranInvalidCaseByThrowCheckException.add(user);         }          Assert.assertTrue(isSuccess);      }
  失效原因:  spring默认只会回滚非检查异常和error异常
  解决方案:  配置rollbackFor 3、场景三:业务自己捕获了异常 @Transactional     public boolean add(User user) {         boolean isSuccess = userService.save(user);         try {             int i = 1 % 0;         } catch (Exception e) {          }         return isSuccess;     }   @Test     public void testCatchExecption() throws Exception{         boolean randomBoolean = new Random().nextBoolean();         boolean isSuccess = false;         TranInvalidCaseWithCatchException tranInvalidCaseByThrowCheckException = applicationContext.getBean(TranInvalidCaseWithCatchException.class);         if(randomBoolean){             randomBoolean = new Random().nextBoolean();             if(randomBoolean){                 System.out.println("将异常原样抛出");                 tranInvalidCaseByThrowCheckException.save(user);             }else{                 System.out.println("设置TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();");                 tranInvalidCaseByThrowCheckException.addWithRollBack(user);             }         }else{             System.out.println("业务自己捕获了异常");             tranInvalidCaseByThrowCheckException.add(user);         }          Assert.assertTrue(isSuccess);      }
  失效原因:  spring事务只有捕捉到了业务抛出去的异常,才能进行后续的处理,如果业务自己捕获了异常,则事务无法感知
  解决方案:
  1、将异常原样抛出;
  2、设置TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 4、场景四:切面顺序导致@Service public class TranInvalidCaseWithAopSort {      @Autowired     private UserService userService;      @Transactional     public boolean save(User user) {         boolean isSuccess = userService.save(user);         try {             int i = 1 % 0;         } catch (Exception e) {             throw new RuntimeException();         }         return isSuccess;     }    } @Aspect @Component @Slf4j public class AopAspect {       @Around(value = " execution (* com.github.lybgeek.transcase.aopsort..*.*(..))")     public Object around(ProceedingJoinPoint pjp){          try {             System.out.println("这是一个切面");            return pjp.proceed();         } catch (Throwable throwable) {             log.error("{}",throwable);         }          return null;     } }
  失效原因:  spring事务切面的优先级顺序最低,但如果自定义的切面优先级和他一样,且自定义的切面没有正确处理异常,则会同业务自己捕获异常的那种场景一样
  解决方案:
  1、在切面中将异常原样抛出;
  2、在切面中设置TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 5、场景五:非public方法@Service public class TranInvalidCaseWithAccessPerm {          @Autowired         private UserService userService;          @Transactional         protected boolean save(User user){             boolean isSuccess = userService.save(user);             try {                 int i = 1 % 0;             } catch (Exception e) {                 throw new RuntimeException();             }             return isSuccess;         }  } public class TranInvalidCaseWithAccessPermTest {      public static void main(String[] args) {         ConfigurableApplicationContext context = SpringApplication.run(Application.class);         TranInvalidCaseWithAccessPerm tranInvalidCaseWithAccessPerm = context.getBean(TranInvalidCaseWithAccessPerm.class);         boolean isSuccess = tranInvalidCaseWithAccessPerm.save(UserUtils.getUser());          System.out.println(isSuccess);      } }
  失效原因:  spring事务默认生效的方法权限都必须为public
  解决方案:
  1、将方法改为public;
  2、修改TansactionAttributeSource,将publicMethodsOnly改为false【这个从源码跟踪得出结论】
  3、开启 AspectJ 代理模式【从spring文档得出结论】 文档如下
  Method visibility and @Transactional
  When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.
  具体步骤:
  1、在pom引入aspectjrt坐标以及相应插件  	org.aspectj 	aspectjrt 	1.8.9    	org.codehaus.mojo 	aspectj-maven-plugin 	1.9 	 		true 		 			 			org.springframework 			spring-aspects 			 		 	 	 		 			                compile                      test-compile                		 	 
  2、在启动类上加上如下配置 @EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
  注:  如果是在idea上运行,则需做如下配置
  4、直接用TransactionTemplate
  示例:     @Autowired     private TransactionTemplate transactionTemplate;      private void process(){         transactionTemplate.execute(new TransactionCallbackWithoutResult() {             @Override             protected void doInTransactionWithoutResult(TransactionStatus status) {                 processInTransaction();             }         });      } 6、场景六:父子容器
  失效原因:  子容器扫描范围过大,将未加事务配置的serivce扫描进来
  解决方案:
  1、父子容器个扫个的范围;
  2、不用父子容器,所有bean都交给同一容器管理
  注:  因为示例是使用springboot,而springboot启动默认没有父子容器,只有一个容器,因此就该场景就演示示例了 7、场景七:方法用final修饰    @Transactional     public final boolean add(User user, UserService userService) {         boolean isSuccess = userService.save(user);         try {             int i = 1 % 0;         } catch (Exception e) {             throw new RuntimeException();         }         return isSuccess;     }
  失效原因:  因为spring事务是用动态代理实现,因此如果方法使用了final修饰,则代理类无法对目标方法进行重写,植入事务功能
  解决方案:
  1、方法不要用final修饰 8、场景八:方法用static修饰  @Transactional     public static boolean save(User user, UserService userService) {         boolean isSuccess = userService.save(user);         try {             int i = 1 % 0;         } catch (Exception e) {             throw new RuntimeException();         }         return isSuccess;     }
  失效原因:  原因和final一样
  解决方案:
  1、方法不要用static修饰 9、场景九:调用本类方法   public boolean save(User user) {         return this.saveUser(user);     }      @Transactional     public boolean saveUser(User user) {         boolean isSuccess = userService.save(user);         try {             int i = 1 % 0;         } catch (Exception e) {             throw new RuntimeException();         }         return isSuccess;     }
  失效原因:  本类方法不经过代理,无法进行增强
  解决方案:
  1、注入自己来调用;
  2、使用@EnableAspectJAutoProxy(exposeProxy = true) + AopContext.currentProxy() 10、场景十:多线程调用 @Transactional(rollbackFor = Exception.class)     public boolean save(User user) throws ExecutionException, InterruptedException {          Future future = executorService.submit(() -> {             boolean isSuccess = userService.save(user);             try {                 int i = 1 % 0;             } catch (Exception e) {                 throw new Exception();             }             return isSuccess;         });         return future.get();       }
  失效原因:  因为spring的事务是通过数据库连接来实现,而数据库连接spring是放在threadLocal里面。同一个事务,只能用同一个数据库连接。而多线程场景下,拿到的数据库连接是不一样的,即是属于不同事务 11、场景十一:错误的传播行为 @Transactional(propagation = Propagation.NOT_SUPPORTED)     public boolean save(User user) {         boolean isSuccess = userService.save(user);         try {             int i = 1 % 0;         } catch (Exception e) {             throw new RuntimeException();         }         return isSuccess;     }
  失效原因:  使用的传播特性不支持事务 12、场景十二:使用了不支持事务的存储引擎
  失效原因:  使用了不支持事务的存储引擎。比如mysql中的MyISAM 13、场景十三:数据源没有配置事务管理器
  注:  因为springboot,他默认已经开启事务管理器。org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration。因此示例略过 14、场景十四:被代理的类过早实例化@Service public class TranInvalidCaseInstantiatedTooEarly implements BeanPostProcessor , Ordered {      @Autowired     private UserService userService;       @Transactional     public boolean save(User user) {         boolean isSuccess = userService.save(user);         try {             int i = 1 % 0;         } catch (Exception e) {             throw new RuntimeException();         }         return isSuccess;     }      @Override     public int getOrder() {         return 1;     } }
  失效原因:  当代理类的实例化早于AbstractAutoProxyCreator后置处理器,就无法被AbstractAutoProxyCreator后置处理器增强 总结
  本文列举了14种spring事务失效的场景,其实这14种里面有很多都是归根结底都是属于同一类问题引起,比如因为动态代理原因、方法限定符原因、异常类型原因等 demo链接
  https://github.com/lyb-geek/springboot-learning/tree/master/springboot-transaction-invalid-case

河南水灾,华为到底有没有捐款?华为回应来了,低调得让人敬佩郑州遭遇水灾,各大企业纷纷捐款,网友们也列出了各个企业捐款的名额,马云和马化腾分别捐出了1。5亿和1亿元的资金物资与此同时质疑之声不绝如缕,很多人声称华为没有捐款,那么他究竟有没有低调上线白条嘀嗒出行金融业务只导流?嘀嗒白条,先乘后付,单单享优惠,8月9日,北京商报记者注意到,北京畅行信息技术有限公司旗下移动出行平台嘀嗒出行App上线了更新版本,新功能页面出现了这样一句标语。北京商报记者体验发三星移动部门遇到危机,坐等卢泰文如何解决前两天看到一个报道,内容是关于三星S系列的。大数据显示自三星S10之后,三星S系列的销量是一年不如一年,一代不如一代。最新的三星S21系列上半年仅卖出1350万台左右,这根本不是三手把手带你入坑抓包神器MitmProxy开源前线(IDOpenSourceTop)猿妹综合整理综合自httpsearthly。devblogmitmproxy你是否会对应用程序正在发出的请求感到好奇,以及它会返回什么响应曝MIUI13将大改!这次还会辜负米粉们的期望吗?目前各大手机厂商都在着重打造自家的操系统,像魅族的Flyme和OPPO的ColorOS今年都取得非常不错的口碑反而今年小米MIUI12。5的表现只能用差强人意来形容,而且小米也下决这是为何?华为再遭美国打压,美运营商却苦不堪言众所周知,华为5G技术处于世界一流水平,威胁到美国利益因而遭受不公平待遇。从最开始的实体名单,到华为5G设备网络安全威胁论,再到台积电拒绝为华为生产高端芯片,美国对华为的打压可谓是仅3149元,6400万三摄12GB256GB,还有65W快充,网友开始纠结了由于每个人对产品的需求不同,为了迎合消费者的需求,厂商往往会推出不同定位的产品,比如相同价格条件下,你可以买到主打拍照的A产品,也可以买到主打高性价比的B产品。但是,如果你不懂行情一加8T,直降800元,是否值得购买哈喽大家好,我是你们的老朋友小生,每天都会给大家更新我的原创内容,今天我们来讲讲一款高性能5G手机一加8T。外观方面,采用了这种8T的柔性直屏设计,分辨率为1080P,刷新率120检察院出手!腾讯被起诉!微信回应来了北京市海淀区厂洼西路8号海淀区人民检察院公告称,该院在履行职责中发现,深圳市腾讯计算机系统有限公司的微信产品青少年模式不符合中华人民共和国未成年人保护法相关规定,侵犯未成年人合法权当以太坊EIP1559遇上NFT,12小时已销毁3000枚ETH昨晚,随着以太坊伦敦硬分叉升级的正式完成,EIP1559的效用已经开始发挥。对于以太坊社区而言,这是一个特殊的时刻,它足足酝酿了2年的时间,而EIP1559的激活更新了以太坊的费用重磅!腾讯阿里互通迎来重大进展自国内互联网巨头以生态为名,在没有边界的互联网上拉帮结派圈地自萌以来,国内互联网环境仿佛一下子倒退20年,甚至还不如20年前当时我们想听音乐可以直接在网上下载一整张碟,但现在想完整
面试被问,Java里的for()与while(true),哪个更快?在JDK8u的jdk项目下做个很粗略的搜索mymbpUsersmeworkspacejdk8ujdksrcegrepnrfor(s?s?。wcl369mymbpUsersmewor阑夕元宇宙还没捂热,Web3又是什么鬼文阑夕互联网前沿概念快要不够用了。曾经短暂担任过美国货币监理署代理署长的BrianBrook,在最近一场国会听证会上向议员们解释何为Web3的视频片段受到盛传,被第一时间加上中文字联想这艘船将驶向何方,科技还是金融联想成为自媒体口中的唐僧肉不是没有原因的,玩头条这么久真的第一次见专业大v国家智库。都是有头有脸的人物在联想事件中穷追猛打十几期视频上百篇文章。康美药业也没有如何待遇,三聚氰胺我也2022前端(JavaScriptampampampTypeScript)会有什么新的变化?首发知乎httpszhuanlan。zhihu。comp444556803注以下只是个人比较熟悉的部分,在浩瀚的前端世界,只是沧海一粟。MonorepoMonorepo成标配,pn华为Mate50X或支持5G?7。2英寸直屏6050mAh,花粉等到了这两年,华为手机业务受阻,本以为其款新机量会有所下降,没想到华为手机却越挫越勇,新机量不仅没减少且比往年还要多。在官宣了新一代折叠屏手机华为P50Pocket之后,华为又一款新机华五分钟学会手机投屏到电脑的5种方法前段时间有很多的朋友在后天问关于手机投屏到电脑的方法,今天就总结整理了5种方法,其实这些都是很简单的,那么接下来就话不多说,来教教大家怎么操作吧。方法一1我们可以通过Win10自带Java,反射机制,反射调用,静态方法,实例方法,Setter和Getter说明参考内容1反射机制,调用属性(静态非静态)2反射机制,调用构造方法(静态非静态)。gettersetter方法定义一些方法来操作成员变量,每个方法都必须有一个有意义的名称,所以让你的冬季不再寒冷,云米石墨烯AI对流电暖器,你忠实的朋友其实作为一个北方人,对天气的变化十分的敏感,主要是我们这里一年四季气候爱恨分明!到了冬季下雪结冰是常见的事情,一般这个时候集中供暖就开始了。不过根据我这么多年的经验,在功能开始和结小米米家零冷水燃气热水器S1预售近日小米零冷水燃气热水器S1开启预售,小米最终还是进入燃气热水器行业了,2018年小米发布米家空调时,就断言小米一定会进入热水器行业,全屋智能家居怎么会少得了,天天都用的热水器呢!商汤科技三名高管年薪达11。92亿?真相是这样的21世纪经济报道记者白杨北京报道近日,关于商汤科技三名高管年薪11。92亿的消息引发了行业热议。流传的年薪统计显示,商汤科技董事会执行主席执行董事行政总裁徐立的年薪为5。12亿,商3款电动车,最快1小时充满,最大续航200公里,适合跑长途与外卖电动车由于使用成本低,灵活方便受到了很多外卖员的欢迎,现在大部分外卖员使用的是电动车作为交通工具,不过外卖员对电动车的要求比较高,首先是需要续航里程远,因为每天他们需要跑几百公里,