springmvc注解详解,spring自定义注解
关注微信公众号:全栈888
本文详细总结了八个禁用了Java Spring事务注释@transactional的场景。 请作为参考。 以下是详细内容。
首先,谈谈自己最近遇到的漏洞:
@Transactionalservice A () try ) insert ); 服务b.update (; }catch () { throw new RunTimeException ); }} serviceB () { @Transactional update ) ) try ) mapperb.update ); }catch () { throw new RunTimeException ); } }} mapperB () try )/dosomething…returntrue; }catch () { return false; }在上面的示例中,//doSomething…中存在SQL执行异常,但无法回滚serviceA插入。 根本原因是异常位置只返回false,而没有抛出执行异常。 没有抛出到上层。 在serviceB中有慢速执行例外,但只得到了一个false。 因此,不能
一般事务无法回滚的集中情况总结如下。
1、数据库引擎不支持事务
现在以MySQL为例,其MyISAM引擎不支持事务处理操作。 InnoDB才是支持事务的引擎,通常使用InnoDB来支持事务。
2、没有被 Spring 管理
如下例所示:
//servicepublicclassorderserviceimplementsorderservice (@ transactionalpublicvoidupdateorder )//updateorder此时@Service
3、方法不是 public 的
@Transactional只能用于公共方法。 否则事务不会失效。 如果要与非公共方法一起使用,请打开AspectJ代理模式。
以下Spring官方文档:
When using proxies,youshouldapplythe @ transactionalannotationonlytomethodswithpublicvisibility.ifyoudoannotateprotected, 私有分组-可见性methodswiththe @ transactional annotation,no error is raised, buttheannotatedmethoddoesnotexhibittheconfiguredtransactionalsettings.considertheuseofaspectj (see below ) ifyouneedtoanotanotatati
意思如上。
4、自身调用问题
让我们来看两个例子:
@ servicepublicclassorderserviceimplimplementsorderservice {公共语音更新(order order ) updateorder ) order; } @ transactionalpublicvoidupdateorder (订单订单)//更新订单) }updat
e方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的 updateOrder 方法,updateOrder 方法上的事务管用吗?再来看下面这个例子:
@Servicepublic class OrderServiceImpl implements OrderService { @Transactional public void update(Order order) { updateOrder(order); } @Transactional(propagation = Propagation.REQUIRES_NEW) public void updateOrder(Order order) { // update order } }这次在 update 方法上加了 @Transactional,updateOrder 加了 REQUIRES_NEW 新开启一个事务,那么新开的事务管用么?
这两个例子的答案是:不管用!
因为它们发生了自身调用,就调该类自己的方法,而没有经过 Spring 的代理类,默认只有在外部调用事务才会生效,这也是老生常谈的经典问题了。
5、数据源没有配置事务管理器
@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource);}如上面所示,当前数据源若没有配置事务管理器,那也是白搭!
6、不支持事务
来看下面这个例子:
@Servicepublic class OrderServiceImpl implements OrderService { @Transactional public void update(Order order) { updateOrder(order); } @Transactional(propagation = Propagation.NOT_SUPPORTED) public void updateOrder(Order order) { // update order } }Propagation.NOT_SUPPORTED:表示不以事务运行,当前若存在事务则挂起,都主动不支持以事务方式运行了,那事务生效也是白搭。
7、异常被吃了
这个也是出现比较多的场景:
// @Servicepublic class OrderServiceImpl implements OrderService { @Transactional public void updateOrder(Order order) { try { // update order } catch { } } }把异常吃了,然后又不抛出来,事务怎么回滚?
8、异常类型错误
上面的例子再抛出一个异常:
// @Servicepublic class OrderServiceImpl implements OrderService { @Transactional public void updateOrder(Order order) { try { // update order } catch { throw new Exception("更新错误"); } } }这样事务也是不生效的,因为默认回滚的是:RuntimeException,如果你想触发其他异常的回滚,需要在注解上配置一下,如:
@Transactional(rollbackFor = Exception.class)这个配置仅限于 Throwable 异常类及其子类。
本文总结了八种事务失效的场景,其实发生最多就是自身调用、异常被吃、异常抛出类型不对这三个了。
- END -
推荐阅读:
问题定位神器 Arthas 的骚操作,定位线上BUG,超给力
(长文)Java后端从入门到放弃
如何使用PostMan进行接口测试
MySQL 索引失效的几种类型以及解决方式
Docker 容器监控系统初探
互联网最基本的黑话,你知道吗?
跨多个云平台上部署多租户
聊聊另外一个Druid(很全)
高可用Redis服务架构分析与搭建
关注:fullstack888
学习架构知识
互联网后端架构
为了大家更好地交流学习,现提供微信群交流方式!
每周不定期分享学习资源!
添加好友备注:【Java】
长按二维码添加好友,进群技术交流