事务管理-cnblog
4). DishServiceImpl中实现方法saveWithFlavor
页面传递的菜品口味信息,仅仅包含name 和 value属性,缺少一个非常重要的属性dishId, 所以在保存完菜品的基本信息后,我们需要获取到菜品ID,然后为菜品口味对象属性dishId赋值。
具体逻辑如下:
①. 保存菜品基本信息 ;
②. 获取保存的菜品ID ;
③. 获取菜品口味列表,遍历列表,为菜品口味对象属性dishId赋值;
④. 批量保存菜品口味列表;
代码实现如下:
@Autowired private DishFlavorService dishFlavorService; /** * 新增菜品,同时保存对应的口味数据 * @param dishDto */ @Transactional public void saveWithFlavor(DishDto dishDto) { //保存菜品的基本信息到菜品表dish this.save(dishDto); Long dishId = dishDto.getId();//菜品id //菜品口味 List<DishFlavor> flavors = dishDto.getFlavors(); flavors = flavors.stream().map((item) -> { item.setDishId(dishId); return item; }).collect(Collectors.toList()); //保存菜品口味数据到菜品口味表dish_flavor dishFlavorService.saveBatch(flavors); }
说明:
由于在 saveWithFlavor 方法中,进行了两次数据库的保存操作,操作了两张表,那么为了保证数据的一致性,我们需要在方法上加上注解 @Transactional来控制事务。
5). 在引导类上加注解 @EnableTransactionManagement
Service层方法上加的注解@Transactional要想生效,需要在引导类上加上注解 @EnableTransactionManagement, 开启对事务的支持。
@Slf4j @SpringBootApplication @ServletComponentScan @EnableTransactionManagement //开启对事物管理的支持 public class ReggieApplication { public static void main(String[] args) { SpringApplication.run(ReggieApplication.class,args); log.info("项目启动成功..."); } }
事务管理与乐观锁冲突解决方案
- 避免同时出现事务管理和乐观锁
- 出现后如何解决
- 如对一张表进行(重复的update语句),version字段会加1
- 开启事务管理,会把这些update语句同时成功,同时失败
- 而这里会被认为是并发操作,乐观锁生效
- 第二次update,version不匹配
- 所有我们在业务代码中人工将version字段+1
- 开启事务管理,会把这些update语句同时成功,同时失败
- 如对一张表进行(重复的update语句),version字段会加1
@Override @Transactional public void modifyDefaultAddress(Long id) { // 判断id的合法性 AddressBook address = addressBookService.getById(id); if(address==null){ throw new BusinessException(ErrorResult.addressFormError()); } // 将当前用户的所有的收货地址is_default 设为0 Long userId = BaseContext.getUserId(); List<AddressBook> addressBooks = this.allAddress(); addressBooks.forEach(item->{ item.setIsDefault(0); }); // 这里进行二次更新语句需要进行事务处理 addressBookService.updateBatchById(addressBooks); // 将当前id对应的收货地址设置为1 // AddressBook addressBook = new AddressBook(); // addressBook.setId(id); // addressBook.setIsDefault(1); // 开启了事务管理,有开启的乐观锁,这里需要获取修改后的version // addressBooks.forEach(item->{ // if(item.getId()==id){ // address.setVersion(item.getVersion()); // } // }); address.setIsDefault(1); address.setVersion(address.getVersion()+1); // address.setDescription("test1"); addressBookService.updateById(address); // LambdaQueryWrapper<AddressBook> wrapper = new LambdaQueryWrapper<>(); // wrapper.eq() // List<AddressBookVo> addressBookVos = this.allAddress(); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)