专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

踩坑Transactional,你能发现问题在哪么?

  前阵子接手了一段代码,里面用到了transaction注解,了解Spring的小伙伴肯定知道,Transactional是Spring提供的一种控制事务管理的快捷手段。但是我这段程序在运行的时候,经常出现莫名其妙的问题,连夜研究了好久才搞清楚,在这里记录一下,避免大家入坑。1。大家来找茬
  在介绍具体问题之前,我把问题代码简化了一下,看大家能找到其中的问题吗?问题代码1
  下面的这段代码主要是想利用MySQL里面的行锁selectforupdate,来实现简单的分布式锁。但是在实践过程中,发现这个锁好像并没有生效,而且在数据库的里面也没有查找对应transaction连接的信息。ComponentEnableSchedulingpublicclasssomeService{Scheduled(。。。)publicdoSomeWork(){findsomeidbylogicprocesstherelatedinfodoOtherWork(id);}Transactional(isolationIsolation。READCOMMITTED)publicvoiddoOtherWork(id){InfoinforequestMapper。selectByPrimaryKeyForUpdate(id);doSomeFollowingProcess(info);。。。}}问题代码2
  下面代码分两个步骤,第一步会检查相关信息,第二步调用了一个transactional修饰的方法,完成一些基本工作;但在实践中,发现一个非常诡异的问题,在MainWork中,doSomeCheck执行时会抛出nullPointException,debug发现所有autowired进来的service均为空,注释掉doSomeCheck里面的内容后,继续往下执行,却发现doWork能够正常执行,所有的注入均没有问题。ComponentpublicclassMainWork{AutoWiredDetailWorkdetailWorkpublicvoidworkflow(){detailWork。doSomeCheck();detailWork。doWork();}}ComponentpublicclassDetailWork{AutoWiredUsefulServiceusefulService;AutoWiredInfoServiceinfoService;Transactional(isolationIsolation。READCOMMITTED)publicvoiddoWork(){usefulService。doSomeWork();}voiddoSomeCheck(){infoService。getInfo();}}
  大伙看看能发现什么问题吗?2。关于Transactional注解
  Spring支持编程式事务管理和声明式事务管理两种方式。编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后,根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需基于Transactional注解的方式,便可以将事务规则应用到业务逻辑中。
  下图是调用Transactional注解的方法时,Spring内部的时序图。简单来讲就是IOC容器初始化时,会生成Transactional注解所在类的代理对象,然后实际执行中会通过AOP执行代理对象的方法,TransactionAdvisor会在方法调用前判断是否开启事务,在调用结束后,会判断是否提交或回滚事务。
  深入研究代码,我们会发现TransactionInterceptor(事务拦截器)在目标方法执行前后进行拦截,DynamicAdvisedInterceptor(CglibAopProxy的内部类)的intercept方法或JdkDynamicAopProxy的invoke方法会间接调用AbstractFallbackTransactionAttributeSource的computeTransactionAttribute方法,获取Transactional注解的事务配置信息。protectedTransactionAttributecomputeTransactionAttribute(Methodmethod,Classlt;?targetClass){Dontallownopublicmethodsasrequired。if(allowPublicMethodsOnly()!Modifier。isPublic(method。getModifiers())){returnnull;}
  此方法会检查目标方法的修饰符是否为public,不是public则不会获取Transactional的属性配置信息。也就是说protected、private修饰的方法上使用Transactional注解会导致事务无效。
  了解了Transactional的原理之后,我们在回头看看之前的问题,会不会是使用方法不对导致的呢?3。拨云见日问题代码1解析
  下面的代码中,我们在同一个类里面调用了Transactional修饰的方法,其实这样调用的话并没有用到SpringAOP生成的代理对象。从上面的时序图也可以看到,只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。ComponentEnableSchedulingpublicclasssomeService{Scheduled(。。。)publicdoSomeWork(){findsomeidbylogicprocesstherelatedinfodoOtherWork(id);}Transactional(isolationIsolation。READCOMMITTED)publicvoiddoOtherWork(id){InfoinforequestMapper。selectByPrimaryKeyForUpdate(id);doSomeFollowingProcess(info);。。。}}
  那如何解决这种类内调用的问题呢?很简单,可以使用applicationContext直接从IOC容器中将someService类取出来,然后再调用doOtherWork方法即可,这样就能用上SpringAOP生成的代理对象了。
  下面是更改之后的代码,更改之后发现事务生效了,问题解决!ComponentEnableSchedulingpublicclasssomeService{AutowiredprivateApplicationContextapplicationContext;Scheduled(。。。)publicdoSomeWork(){findsomeidbylogicprocesstherelatedinfoSomeServicesomeServiceapplicationContext。getBean(someService。class);someService。doOtherWork(id);}Transactional(isolationIsolation。READCOMMITTED)publicvoiddoOtherWork(id){InfoinforequestMapper。selectByPrimaryKeyForUpdate(id);doSomeFollowingProcess(info);。。。}}问题代码2解析
  下面的代码中,MainWork调用doSomeCheck的时候,会出现null的情况,原因是由于该方法不是public方法,会导致Transactional调用失败。你可能会说这就是普通方法,跟Transactional有什么关系?
  需要注意的是,无论transactional注解在类上还是在方法上,IOC容器都会生成对应类的代理对象,然后使用代理对象去访问对应的方法。在这个例子里面,调用doWork时一切正常,事务也会生效;但是调用doSomeCheck时,从之前的分析可以看到,由于方法不是public,此时事务管理器不会起作用,直接导致所有的autowired未完成注入。修改的方法也很简单,把doSomeCheck改成public就行了。
  这个问题隐藏比较深一些,不清楚原理很难发现这个问题。ComponentpublicclassMainWork{AutoWiredDetailWorkdetailWorkpublicvoidworkflow(){detailWork。doSomeCheck();detailWork。doWork();}}ComponentpublicclassDetailWork{AutoWiredUsefulServiceusefulService;AutoWiredInfoServiceinfoService;Transactional(isolationIsolation。READCOMMITTED)publicvoiddoWork(){usefulService。doSomeWork();}publicvoiddoSomeCheck(){infoService。getInfo();}}4。相关拓展几种事务失效的场景
  上面说到的两个问题,其实就是Transactional注解使用不当,导致失效的两种情形;除此之外,以下几种情况也会导致事务失效:业务代码中存在异常时,使用trycatch语句块捕获,而catch语句块没有thrownewRuntimeExecption异常;(最难被排查到问题且容易忽略)注解Transactional中Propagation属性值设置错误即Propagation。NOTSUPPORTED(一般不会设置此种传播机制)mysql关系型数据库,且存储引擎是MyISAM而非InnoDB,则事务会不起作用(比较少见);业务代码抛出异常类型非RuntimeException,事务失效;Spring默认抛出未检查unchecked异常(继承自RuntimeException的异常)或者Error才回滚事务;其他异常不会触发回滚事务。如果在事务中抛出其他类型的异常,但却期望Spring能够回滚事务,就需要指定rollbackFor属性。
  事务的传播行为
  事务的传播行为也会影响到事务与事务之间的关系,一定要搞清楚,否则经常会出现很奇怪的问题。
  具体来讲有以下几种属性:propagation代表事务的传播行为,默认值为Propagation。REQUIRED,其他的属性信息如下:Propagation。REQUIRED:如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。(也就是说如果A方法和B方法都添加了注解,在默认传播模式下,A方法内部调用B方法,会把两个方法的事务合并为一个事务)Propagation。SUPPORTS:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。Propagation。MANDATORY:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。Propagation。REQUIRESNEW:重新创建一个新的事务,如果当前存在事务,暂停当前的事务。(当类A中的a方法用默Propagation。REQUIRED模式,类B中的b方法加上采用Propagation。REQUIRESNEW模式,然后在a方法中调用b方法操作数据库,然而a方法抛出异常后,b方法并没有进行回滚,因为Propagation。REQUIRESNEW会暂停a方法的事务)Propagation。NOTSUPPORTED:以非事务的方式运行,如果当前存在事务,暂停当前的事务。Propagation。NEVER:以非事务的方式运行,如果当前存在事务,则抛出异常。Propagation。NESTED:和Propagation。REQUIRED效果一样。事务的隔离级别
  SQL标准定义了4种事务隔离级别来避免3种数据不一致的问题。事务等级从高到低,分别为:
  1。Serializable(序列化)
  系统中所有的事务以串行地方式逐个执行,所以能避免所有数据不一致情况。
  但是这种以排他方式来控制并发事务,串行化执行方式会导致事务排队,系统的并发量大幅下降,使用的时候要绝对慎重。
  2。Repeatableread(可重复读)
  一个事务一旦开始,事务过程中所读取的所有数据不允许被其他事务修改。
  一个隔离级别没有办法解决幻影读的问题。
  因为它只保护了它读取的数据不被修改,但是其他数据会被修改。如果其他数据被修改后恰好满足了当前事务的过滤条件(where语句),那么就会发生幻影读的情况。
  其他两种事务隔离等级为:
  3。ReadCommitted(已提交读)
  一个事务能读取到其他事务提交过(Committed)的数据。
  一个事务在处理过程中如果重复读取某一个数据,而且这个数据恰好被其他事务修改并提交了,那么当前重复读取数据的事务就会出现同一个数据前后不同的情况。
  在这个隔离级别会发生不可重复读的场景。
  4。ReadUncommitted(未提交读)
  一个事务能读取到其他事务修改过,但是还没有提交的(Uncommitted)的数据。
  数据被其他事务修改过,但还没有提交,就存在着回滚的可能性,这时候读取这些未提交数据的情况就是脏读。
  在这个隔离级别会发生脏读场景。

为什么能吸引到很多创作者和用户?因为今日头条是字节跳动旗下的一款软件,是一个利用大数据,智能分发优质信息的平台。今日头条平台内容丰富,不论是创作者,还是用户,都能在今日头条学习到很多知识,增长了见识。对于创作者而云电脑哪个好用?个人觉得达龙云电脑就挺不错的。我用龙达云电脑玩了下,就是个人移动网吧。还可以吧,希望便宜点,毕竟天天泡网吧也是用不起,目前最低3块钱一小时。可以试试达龙云电脑,安装后通过手机就能玩你认为俞敏洪是个优秀的企业家吗?所谓的企业家,就是现实社会的资本家,不剥削,搞正经经营能发家吗?良心?天知地知?只是冦以好名而已。当初创业时俞敏洪竟是两手空空,一无所有。创业的成功也许是天意,但他坚定不移的信念和请问B2驾驶证好找工作吗?B2驾照工作好找吗?A2驾照十几年驾龄说了个人观点,希望对你有帮助如果您这个时代还仅仅只是以驾驶证这一项目单一的技术来找工作的话,收入一定不会太让你满意,甚至会低于你最终的生活需求宝宝大便前干后稀是怎么回事?宝宝大便前干后稀是怎么回事宝宝大便前干后稀多是消化不良导致的。宝宝的胃肠道功能发育还不完善,肠道内菌群平衡也还未建立完全。如果在哺乳期,妈妈的饮食改变,或者给宝宝添加辅食不当,宝宝孩子3岁之后喝奶粉到底好不好?看到图片,发现你家孩子3岁了还用的奶瓶,那么就先说一下孩子使用奶瓶的问题。长时间使用奶瓶的危害一般建议在宝宝在18个月的时候就戒掉奶瓶。因为长期使用奶瓶的孩子因为用力吸吮,会导致宝买6D22470mm28红圈好,还是买5D4单机好?针对是选择佳能EOS6DMarkII和EOS5DMarkIV这个话题,可能也是困扰很多当下想选择佳能单反相机用户的普遍问题。作为目前数字单反相机技术不断革新和飞速发展推陈出新的时代朱芳雨称林叔是他的大恩人,林叔对他的帮助有多大?众所周知,广东男篮的第一任老板是陈林(现任老板陈海涛的父亲),大家亲切地称之为林叔。在他离世后,朱芳雨在社交平台上表示,林叔是他的大恩人。那么,林叔对朱芳雨的帮助到底有多大呢?19为什么国产手机的文件夹都是英文,能不能改成中文?谢邀!依然是正经的回答这个问题。我从两方面来表达我的观点。1,必要性。虽然安卓手机的普及率非常高,但是关心手机的文件夹的人还是非常少的,我认为连5都不到。至少有70的人都没使用过文华为鸿蒙OS首批正式版升级名单公布,共18款机型,有你的手机机型吗,你怎么看?p30,升级耗时60分钟,未发现掉原有内容。最惊喜是指纹解锁,再难有不识别靠输密码。顺滑的不得了,仿若瘦身。升级鸿蒙,弃用安卓,一分分力,也算贡献哈我是mate305G,在第一批就手机厂商卖不出去的手机里面的处理器,到该手机停产以后是怎么处理的?手机处理器都是很精密的芯片,而且集成度特别高,如果真的出现停产后的库存,哪怕真的一部也卖不出去了,厂商们也不会把芯片拆了拿到别处用,一是复杂度和成本太高,二是厂商们都有一套控制库存
陪伴李泽楷近5年!郭嘉文才是真正的人间清醒都说飞上枝头变凤凰并不是那么容易的事,但是出身小康家庭的郭嘉文却做到了,我们都知道就算是港姐冠军也不一定能结识到超级富豪,更何况是港姐季军了。而作为季军出身的郭嘉文虽然没有凭借出道在c罗阴影下仍然闪耀的曼联边锋纳尼当曼联在2009年以8000万英镑价格,出售克里斯蒂亚诺罗纳尔多时,他的继任者将继续成为俱乐部拥有的最好的边锋之,但他们从未完全摆脱CR7的阴影如果说曼联在过去20年里,得到了最好纳达尔不舒服了!德约科维奇我受到不公对待,纳达尔一直不死心2022对于德约科维奇是喜忧参半的一年,由于德约未接种疫苗以及一系列骚操作,导致德约有两项大满贯无法参加,并且让纳达尔渔翁得利,夺走了年初的澳网,眼睁睁看着宿敌完成了与之同样的双圈火箭惨败开拓者看不到希望!塞拉斯还是下课吧?火箭队遭遇开拓者,任何人都会想到是输球,但是输的一点价值也没有。最关键的是攻防两端没有任何亮点,一点希望也看不到。此役,火箭队也不是没有想法,想利用努尔基奇防守端出不来的特点,用一连战连捷!莱斯特城不仅摆脱降级区,更在征服财政危机纵然在豪门林立的英超赛场,绰号为狐狸城的莱斯特城依然是美丽的独特存在。回首201516赛季,身为二年级生的莱斯特城面对英超豪强,硬是在在传奇主帅拉涅利的带领下不畏挑战屡屡逆转,最终曝德赫亚愿降薪一半续约曼联!球探考察两新门将,滕哈格将做抉择本赛季开始至今,只有一名球员踢满曼联所有的比赛,他就是31岁的门将大卫德赫亚。然而,出场最多的球员,却也是球队主力阵容里未来最不明确的一人,许多人认为,本赛季结束后,他就会被滕哈格火箭负开拓者,比赛无一次领先,继续俯冲文班亚马火箭四连客的第二场,来到波特兰面对暂列西部第一的开拓者,本场比赛利拉德伤病缺席的情况下,火箭还是被开拓者按在地上反复摩擦。本赛季还在重建之中的火箭队看样子还是想在摆一年,目前5胜1美人有卧蚕,你只有脾虚造成的眼袋这世界上,有卧蚕的人不多,但是有眼袋的人却不在少数。虽然卧蚕和眼袋看起来有点像,但是我们都能一眼区分出来。因为有卧蚕的眼睛是精神的,卧蚕下面的脸也是清清爽爽的而有眼袋的眼睛往往是无2022年智能手表怎么选智能手表推荐现在很多小伙伴已经不再满足于机械手表的单一功能,而是把更多的注意力放在智能手表之上,因为现在的智能手表不但拥有健康监测运动数据监测移动支付等功能,而且在外观设计上也更加轻便和科技感李鸿忠深刻领悟两个确立的决定性意义,推动党的二十大精神学习宣传贯彻走深走实10月31日,市委书记市委党校校长李鸿忠在市委党校主持召开学习宣传贯彻党的二十大精神座谈会,强调要全面落实中共中央关于认真学习宣传贯彻党的二十大精神的决定,充分发挥全市党校系统干部三星台积电面临专利侵权案调查,高通公司被点名三星和台积电正面临美国国际贸易委员会(USITC)的调查,指控涉及芯片和包含这些芯片的移动设备的专利侵权。美国国贸中心表示,将根据纽约布朗克斯维尔的DaedalusPrimeLLC
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网