SpringBoot项目开启事务控制

所谓事务,就是让程序拥有原子性,即要么同时成功,要么同时失败。

案例

我们来看这段代码:

@Service
public class VideoOrderServiceImpl implements VideoOrderService {

    @Autowired
    private VideoOrderMapper videoOrderMapper;

    @Autowired
    private VideoMapper videoMapper;

    @Autowired
    private EpisodeMapper episodeMapper;

    @Autowired
    private PlayRecordMapper playRecordMapper;

    /**
     * 下单模块
     * 未来版本:优惠券抵扣、风控用户检测、生成订单基础信息、生成支付信息
     * @param userId
     * @param videoId
     * @return
     */
    @Override
    @Transactional
    public int save(int userId, int videoId) {
        // 判断是否已经购买
        VideoOrder videoOrder = videoOrderMapper.findByUserIdAndOrderIdAndState(userId,videoId,1);
        if (videoOrder != null){
            return 0;
        }
        Video video = videoMapper.findById(videoId);
        VideoOrder newVideoOrder = new VideoOrder();
        newVideoOrder.setCreateTime(new Date());
        newVideoOrder.setOutTradeNo(UUID.randomUUID().toString());
        newVideoOrder.setState(1);
        newVideoOrder.setTotalFee(video.getPrice());
        newVideoOrder.setUserId(userId);
        newVideoOrder.setVideoId(videoId);
        newVideoOrder.setVideoImg(video.getCoverImg());
        newVideoOrder.setVideoTitle(video.getTitle());
        int rows = videoOrderMapper.saveOrder(newVideoOrder);

        // 生成播放记录
        if (rows == 1){
            Episode episode = episodeMapper.findFirstEpisodeByVideoId(videoId);
            if (episode == null){
                throw new XDException(-1,"视频没有集信息,请运营人员检查");
            }

            PlayRecord playRecord = new PlayRecord();
            playRecord.setCreateTime(new Date());
            playRecord.setEpisodeId(episode.getId());
            playRecord.setCurrentNum(episode.getNum());
            playRecord.setUserId(userId);
            playRecord.setVideoId(videoId);
            playRecordMapper.saveRecord(playRecord);
        }

        return rows;
    }
}

这是我现在写的K12项目中的一段接口实现类代码。这段代码的功能相信大家看注释就能看出来,就是用户在下单时同时生成播放记录,当然刚下单时的播放记录是从第一个视频开始的

那么,如果在这两个逻辑之前出现了异常,比如我在【// 生成播放记录】该注解的上一行加上“int i = 1/0;” 显然“int i = 1/0;”会导致代码异常。

那该程序在执行异常代码之前的生成订单逻辑的代码中是没有异常的,但是执行完该逻辑后,发生了异常,那么【生成播放记录】肯定不会执行成功。

如果你看数据库会发现,订单确实生成了,但是播放记录没有生成,这显然不符合实际需求。

解决方法

开启事务控制:

  • 在启动类上加上注解 @EnableTransactionManagement
  • 在业务类,或者业务方法上加注解 @Transactional

OK,只需要这简单的两个注解即可完成!
但是注意,最好在有需求的业务方法上加 @Transactional,因为在业务类加该注解是默认开启该业务类中的全部方法事务,影响性能。

这样如果两个逻辑之间,或者其中一个逻辑出现了异常,那么都不会执行成功,则数据库也不会添加数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二炮

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值