您的位置:首页 > 教育 > 锐评 > 香港最新消息通关_沈阳企业网站开发定制_什么是百度权重_从事网络销售都有哪些平台呢

香港最新消息通关_沈阳企业网站开发定制_什么是百度权重_从事网络销售都有哪些平台呢

2025/2/27 21:46:52 来源:https://blog.csdn.net/u013521220/article/details/143565083  浏览:    关键词:香港最新消息通关_沈阳企业网站开发定制_什么是百度权重_从事网络销售都有哪些平台呢
香港最新消息通关_沈阳企业网站开发定制_什么是百度权重_从事网络销售都有哪些平台呢

在Spring Boot中,你可以通过使用@Transactional注解来给方法增加事务支持,但是有时候使用不当会导致事务失败,会产生数据无法一致性这种严重的数据问题,可能出现的场景如下。

一、实例背景介绍

1、数据库数据表sys_user中description字段“要求非空”,但是我们新增时候传null,继而导致保存失败,事务被触发导致批量数据会全部会被回滚。

2、Springboot中使用事务需要在启动类中开启事务@EnableTransactionManagement和在方法或者类上使用注解@Transactional

二、数据库引擎不支持事务

这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用 InnoDB。

从 MySQL 5.5.5 开始的默认存储引擎是:InnoDB,之前默认的都是:MyISAM,所以这点要值得注意,底层引擎不支持事务再怎么操作都是无济于事。

三、没有被 Spring 管理

// @Service
public class OrderServiceImpl implements OrderService {@Transactionalpublic void updateOrder(Order order) {// update order}
}

上方例子中,@Service注解被注释了。这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了。

四、事务方法非public修饰

由于Spring的事务是基于AOP的方式结合动态代理来实现的。因此事务方法一定要是public的,这样才能便于被Spring做事务的代理和增强。

而且,在Spring内部也会有一个 org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource类,去检查事务方法的修饰符。

    @ApiOperation("添加")@PostMapping("/add")@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)protected void addUser(@RequestBody User user) {user.setUserName("火箭");user.setDescription("Rocket");iUserService.save(user);user.setUserName("巫师");user.setDescription(null);iUserService.save(user);}

五、非事务方法调用事务方法 

Spring会给带有@Transactional注解类生成一个动态代理对象,对方法做增加实现事务效果。

非事务方法直接调用,就会导致对象无法被Spring代理对象获取到,继而导致事务失败。

@ApiOperation("添加")@PostMapping("/add")//@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)public void addUser(@RequestBody User user) {this.saveUser(user);}@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)public void saveUser(User user) {user.setUserName("火箭");user.setDescription("Rocket");iUserService.save(user);user.setUserName("巫师");user.setDescription(null);iUserService.save(user);}

六、事务方法的异常被捕获

而Spring的事务管理就是要感知业务方法的异常,当捕获到异常后才会回滚事务,

现在异常被捕获,且没有抛出,相当于异常被程序员私下处理掉了,就会导致Spring无法感知事务异常,自然不会回滚,事务就失效了。

@ApiOperation("添加")@PostMapping("/add")@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)public void addUser(@RequestBody User user) {try{user.setUserName("火箭");user.setDescription("Rocket");iUserService.save(user);user.setUserName("巫师");user.setDescription(null);iUserService.save(user);}catch (Exception e){e.printStackTrace();}}

七、事务异常类型不对

Spring的事务管理默认感知的异常类型是RuntimeException或者RuntimeException的子类,当事务方法内部抛出了一个IOException时,不会被Spring捕获,因此就不会触发事务回滚,事务就失效了。 

1、异常被处理,没有正确抛出
@Service
public class OrderServiceImpl implements OrderService {@Transactionalpublic void updateOrder(Order order) {try {// update order} catch {}}
}

try..catch..捕获了一场,然而catch中还没有将异常抛出,所以springboot捕获不到异常,就无法进行回滚! 

2、异常抛出类型不对
@Service
public class OrderServiceImpl implements OrderService {@Transactionalpublic void updateOrder(Order order) {try {// update order} catch {throw new Exception("更新错误");}}
}

try..catch..虽然捕获了异常且跑出了Exception异常,但是springboot只有捕获到RuntimeException异常时才会触发回滚。 

八、事务传播行为设置不对

1、因为事务之间的传播会相互影响,一定要慎用传播行为,注意外部事务与内部事务之间的关系。

@Transactional
public void createOrder(){// 生成订单insertOrder();// 扣减库存reduceStock();throw new RuntimeException("业务异常");
}@Transactional  // 默认的是如果当前没有事务,自己创建事务,如果有事务则加入
public void insertOrder() {}// 不管当前方法所在方法有没有都开启一个事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void reduceStock() {}

在示例代码中,事务的入口是createOrder()方法,会开启一个事务,可以成为外部事务。在createOrder()方法内部又调用了insertOrder()方法和reduceStock()方法。这两个都是事务方法。

不过,reduceStock()方法的事务传播行为是REQUIRES_NEW,这会导致在进入reduceStock()方法时会创建一个新的事务,可以成为子事务。insertOrder()则是默认,因此会与createOrder()合并事务。

因此,当createOrder方法最后抛出异常时,只会导致insertOrder方法回滚,而不会导致reduceStock方法回滚,因为reduceStock是一个独立事务。 

2、 Propagation.NOT_SUPPORTED: 表示不以事务运行,当前若存在事务则挂起。这是主动配置了事务不生效,所以事务就不存在。

 @Transactional(propagation = Propagation.NOT_SUPPORTED)public void updateOrder(Order order) {// update order}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com