Spring Data JPA 解决秒杀系统中减库存操作

之前更新库存逻辑是先拿到 Goods 对象,然后将库存设置为当前库存减1,然后调用 GoodsRepository.save() 方法保存更新后的对象。这个处理逻辑会导致超售。

先上部分控制逻辑代码:

Goods goods = goodsRepository.findById(id).get();
goods.setNumber(goods.getNumber() - 1);
if (goods.getNumber() <= 0) {throw new SeckillException(ResultEnum.END);
}
goodsRepository.save(goods);

 

新的方法是使用 @Transactional 注解管理事务和 @Query 注解自定义查询方法。

首先在 GoodsRepository 接口中定义一个减库存方法:

    @Transactional
    @Modifying(clearAutomatically = true)
    @Query(value = "update Goods set number = number -1 where id=?1 and number>0")
    int reduceStock(Integer id);

要注意的几点是:

1.@Transactional 注解要使用 org.springframework.transaction.annotation.Transactional 包下的。( javax.transaction.Transactional 包下的一般是JAVA EE项目使用)

2.@Query 注解中 nativeQuery 项默认为 false,代表使用 JPQL 语句查询。nativeQuery = true 代表使用原生 SQL 语句查询。 下面两段代码功能一致:

@Query(value = "update Goods set number = number -1 where id=?1 and number>0")
@Query(value = "update goods set number = number -1 where id=?1 and number>0",nativeQuery = true)

 

然后逻辑代码可以更新为:

Goods goods = goodsRepository.findById(id).get();
int state = reduceStock(id);
if(state != 0){
  //保存订单
}

 

更新代码后测试未出现超售现象。

 

 

参考链接:

https://www.ibm.com/developerworks/cn/java/j-master-spring-transactional-use/index.html

https://www.oracle.com/technetwork/articles/vasiliev-jpql-085775-zhs.html?printOnly=1

https://zhuanlan.zhihu.com/p/29611306

https://blog.csdn.net/zt15732625878/article/details/78378995

posted @ 2019-05-16 02:10  1x11  阅读(687)  评论(0编辑  收藏  举报