前序准备

将gulimall-ware注册到nacos,修改配置文件,主启动类加上@EnableDiscoveryClient和@EnableTransactionManagement注解。
配置网关,新增路由规则

  1. # 要放在renren-fast的转发之前
  2. - id: ware_route
  3. uri: lb://gulimall-ware
  4. predicates:
  5. - Path=/api/gulimallware/**
  6. filters:
  7. - RewritePath=/api/(?<segment>.*), /$\{segment}

一、仓库维护

这里需要完善条件查询
image.png

  1. @Override
  2. public PageUtils queryPage(Map<String, Object> params) {
  3. QueryWrapper<WareInfoEntity> wrapper = new QueryWrapper<>();
  4. String key = (String) params.get("key");
  5. if (!StringUtils.isEmpty(key)) {
  6. wrapper.eq("id", key).or()
  7. .like("name", key)
  8. .or().like("address", key)
  9. .or().like("areacode", key);
  10. }
  11. IPage<WareInfoEntity> page = this.page(
  12. new Query<WareInfoEntity>().getPage(params),
  13. wrapper
  14. );
  15. return new PageUtils(page);
  16. }

二、商品库存

2.1 查询sku库存

https://easydoc.net/s/78237135/ZUqEdvA4/hwXrEXBZ
image.png
进入商品库存页面会发送/waresku/list给后台,这里我们需要完善条件查询,直接在原来的方法上修改。

  1. @Override
  2. public PageUtils queryPage(Map<String, Object> params) {
  3. /**
  4. * skuId: 1
  5. * wareId: 2
  6. */
  7. QueryWrapper<WareSkuEntity> wrapper = new QueryWrapper<>();
  8. String skuId = (String) params.get("skuId");
  9. if (!StringUtils.isEmpty(skuId)) {
  10. wrapper.eq("sku_id", skuId);
  11. }
  12. String wareId = (String) params.get("wareId");
  13. if (!StringUtils.isEmpty(wareId)) {
  14. wrapper.eq("ware_id", wareId);
  15. }
  16. IPage<WareSkuEntity> page = this.page(
  17. new Query<WareSkuEntity>().getPage(params),
  18. wrapper
  19. );
  20. return new PageUtils(page);
  21. }

2.2 新增sku库存(先完成采购单维护)

新增库存不是直接在商品库存页面进行新增,而是通过采购。所以我们需要先完成采购的相关功能。

三、采购单维护

image.png

3.1 采购需求

image.png
采购需求来自两方面:

  1. 人工添加的采购需求
  2. 低库存预警,系统自动发出的采购需求

    3.1.1 查询采购需求

    https://easydoc.net/s/78237135/ZUqEdvA4/Ss4zsV7R 查询wms_purchase_detail表,前端会发送查询条件,需要进行条件查询。

    1. @Override
    2. public PageUtils queryPage(Map<String, Object> params) {
    3. /**
    4. * key: '华为',//检索关键字
    5. * status: 0,//状态
    6. * wareId: 1,//仓库id
    7. */
    8. QueryWrapper<PurchaseDetailEntity> wrapper = new QueryWrapper<>();
    9. String key = (String) params.get("key");
    10. // and (purchase_id = key or sku_id = key)
    11. if (!StringUtils.isEmpty(key)) {
    12. wrapper.and(w -> {
    13. w.eq("purchase_id", key).or().eq("sku_id", key);
    14. });
    15. }
    16. String status = (String) params.get("status");
    17. if (!StringUtils.isEmpty(status)) {
    18. wrapper.eq("status", status);
    19. }
    20. String wareId = (String) params.get("wareId");
    21. if (!StringUtils.isEmpty(wareId)) {
    22. wrapper.eq("ware_id", wareId);
    23. }
    24. IPage<PurchaseDetailEntity> page = this.page(
    25. new Query<PurchaseDetailEntity>().getPage(params),
    26. wrapper
    27. );
    28. return new PageUtils(page);
    29. }

3.1.2 合并采购需求

新增采购单

在合并采购单之前,需要新增采购单。
image.png
image.png
image.png
此时前端会发送请求http://localhost:88/api/gulimallware/purchase/unreceive/list?t=1647226496404 查询新建的和已分配的采购单(采购单有五种状态:新建、已分配、已领取、已完成、有异常五种状态;其中只有新建和已分配的采购单能够对采购内容进行修改)。
https://easydoc.net/s/78237135/ZUqEdvA4/cUlv9QvK

  1. /**
  2. * 查询新建和已分配状态的采购单
  3. */
  4. // /ware/purchase/unreceive/list
  5. @GetMapping("/unreceive/list")
  6. public R unreceiveList(@RequestParam Map<String, Object> params) {
  7. PageUtils page = purchaseService.queryPageUnreceivePurchase(params);
  8. return R.ok().put("page", page);
  9. }
  1. /**
  2. * 查询新建和已分配状态的采购单
  3. * @param params
  4. * @return
  5. */
  6. @Override
  7. public PageUtils queryPageUnreceivePurchase(Map<String, Object> params) {
  8. // 采购单的status必须是0(新建)或者是1(已分配)
  9. IPage<PurchaseEntity> page = this.page(
  10. new Query<PurchaseEntity>().getPage(params),
  11. new QueryWrapper<PurchaseEntity>().eq("status", 0).or().eq("status", 1)
  12. );
  13. return new PageUtils(page);
  14. }

采购单分配给采购人员

合并采购单的时候,展示的应该是采购单的编号和采购人员,所以需要给采购单分配采购人员。
image.png
image.png

合并采购需求

https://easydoc.net/s/78237135/ZUqEdvA4/cUlv9QvK
当选定采购单时,会将采购需求合并到目标采购单;若没有选定采购单,则新建采购单。
image.png
新建一个MergeVo接收前端传过来的数据(采购单ID和采购计划ID)

  1. package com.atguigu.gulimall.gulimallware.vo;
  2. @Data
  3. public class MergeVo {
  4. private Long purchaseId;
  5. private List<Long> items;
  6. }
  1. /**
  2. * 合并采购需求
  3. */
  4. // /ware/purchase/merge
  5. @PostMapping("/merge")
  6. public R merge(@RequestBody MergeVo vo) {
  7. purchaseService.mergePurchase(vo);
  8. return R.ok();
  9. }

因为采购单和采购计划都有状态属性,新建WareConstant类,存放采购单与采购计划的状态枚举类

  1. package com.atguigu.common.constant;
  2. public class WareConstant {
  3. public enum PurchaseStatusEnum {
  4. CREATED(0, "新建状态"), ASSIGNED(1, "已分配"),
  5. RECEIVE(2, "已领取"), FINISH(3, "已完成"),
  6. ERROR(4, "有异常");
  7. private int code;
  8. private String message;
  9. PurchaseStatusEnum(int code, String message) {
  10. this.code = code;
  11. this.message = message;
  12. }
  13. public int getCode() {
  14. return code;
  15. }
  16. public String getMessage() {
  17. return message;
  18. }
  19. }
  20. public enum PurchaseDetailStatusEnum {
  21. CREATED(0, "新建状态"), ASSIGNED(1, "已分配"),
  22. BUYING(2, "正在采购"), FINISH(3, "已完成"),
  23. FAIL(4, "采购失败");
  24. private int code;
  25. private String message;
  26. PurchaseDetailStatusEnum(int code, String message) {
  27. this.code = code;
  28. this.message = message;
  29. }
  30. public int getCode() {
  31. return code;
  32. }
  33. public String getMessage() {
  34. return message;
  35. }
  36. }
  37. }

方法声明&实现

  1. @Autowired
  2. PurchaseDetailServiceImpl purchaseDetailService;
  3. /**
  4. * 合并采购需求到采购单;若指定采购单,则合并到指定采购单,反之新建采购单合并
  5. * @param vo
  6. */
  7. @Transactional
  8. @Override
  9. public void mergePurchase(MergeVo vo) {
  10. Long purchaseId = vo.getPurchaseId();
  11. if (purchaseId == null) { //没有指定采购单,那么需要新建一个采购单
  12. PurchaseEntity purchaseEntity = new PurchaseEntity();
  13. purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode()); // 设置采购单状态 采购单状态使用一个枚举类
  14. purchaseEntity.setCreateTime(new Date()); // 设置新建时间
  15. purchaseEntity.setUpdateTime(new Date()); // 设置修改时间
  16. this.save(purchaseEntity);
  17. purchaseId = purchaseEntity.getId();
  18. }
  19. List<Long> purchaseDetailIds = vo.getItems(); // 获取需要合并到采购单的采购计划id
  20. Long finalPurchaseId = purchaseId;
  21. // 更新每个id对应的采购计划的属性
  22. List<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailIds.stream().map(item -> {
  23. PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
  24. purchaseDetailEntity.setId(item);
  25. purchaseDetailEntity.setPurchaseId(finalPurchaseId); // 更新采购计划属于哪个采购单
  26. purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode()); // 更新状态
  27. return purchaseDetailEntity;
  28. }).collect(Collectors.toList());
  29. purchaseDetailService.updateBatchById(purchaseDetailEntities); // 批量更新采购计划
  30. // 更新采购单的更新时间
  31. PurchaseEntity purchaseEntity = new PurchaseEntity();
  32. purchaseEntity.setId(purchaseId);
  33. purchaseEntity.setUpdateTime(new Date());
  34. this.updateById(purchaseEntity);
  35. }

3.2 领取采购单

采购单分配以后,被分配人员应该可以看到自己被分配到的采购单,然后领取;领取完成后,采购单的状态会改为已领取。同时,已经被领取的采购单将无法再合并采购需求,同时已经合并的采购需求状态变为正在采购中。(领取采购单不属于前端的操作,我们通过postman来模拟手机上领取采购单)
https://easydoc.net/s/78237135/ZUqEdvA4/vXMBBgw1 领取采购单api文档

  1. /**
  2. * 领取采购单
  3. * @param purchaseIds
  4. * @return
  5. */
  6. // /ware/purchase/received
  7. @PostMapping("/received")
  8. public R receivedPurchase(@RequestBody List<Long> purchaseIds) {
  9. purchaseService.receivedPurchase(purchaseIds);
  10. return R.ok();
  11. }
  1. /**
  2. * 领取采购单
  3. * @param purchaseIds 采购单Id集合
  4. */
  5. @Override
  6. public void receivedPurchase(List<Long> purchaseIds) {
  7. // 1、确认当前采购单是新建或者已分配状态
  8. List<PurchaseEntity> purchaseEntities = purchaseIds.stream().map(id -> {
  9. // 找出purchaseId对应的采购单实体
  10. PurchaseEntity purchase = this.getById(id);
  11. return purchase;
  12. }).filter(item -> { // 选择已分配的采购单
  13. boolean isValiable = item.getStatus() == WareConstant.PurchaseStatusEnum.ASSIGNED.getCode();
  14. return isValiable;
  15. }).map(purchase -> { // 更新采购单的状态为已领取
  16. purchase.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode()); // 状态为已领取
  17. purchase.setUpdateTime(new Date()); // 更新时间
  18. return purchase;
  19. }).collect(Collectors.toList());
  20. // 2、数据库中改变采购单的状态为已领取
  21. this.updateBatchById(purchaseEntities);
  22. // 3、改变采购需求的状态为采购中
  23. purchaseEntities.forEach(item -> {
  24. Long purchaseId = item.getId(); // 获取当前采购单Id
  25. // 找出所有purchase_id对应的采购需求
  26. List<PurchaseDetailEntity> detailEntityList = purchaseDetailService.listDetailByPurchaseId(purchaseId);
  27. // 更新采购需求的状态
  28. List<PurchaseDetailEntity> detailEntities = detailEntityList.stream().map(detail -> {
  29. PurchaseDetailEntity entity = new PurchaseDetailEntity();
  30. entity.setId(detail.getId());
  31. entity.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());
  32. return entity;
  33. }).collect(Collectors.toList());
  34. purchaseDetailService.updateBatchById(detailEntities);
  35. });
  36. }
  1. /**
  2. * 通过采购单Id查询当前采购单下的所有采购计划
  3. * @param purchaseId
  4. * @return
  5. */
  6. @Override
  7. public List<PurchaseDetailEntity> listDetailByPurchaseId(Long purchaseId) {
  8. QueryWrapper<PurchaseDetailEntity> wrapper = new QueryWrapper<>();
  9. wrapper.eq("purchase_id", purchaseId);
  10. List<PurchaseDetailEntity> purchaseDetailEntities = this.list(wrapper);
  11. return purchaseDetailEntities;
  12. }

3.3 完善合并采购需求(视频没写)

确认采购单状态是0,1的时候才能合并采购需求。这里我是按自己思路写的,视频里面没写这些。
我让mergePurchase方法返回一个boolean类项的值,以此来判断合并是否成功。

  1. /**
  2. * 合并采购需求
  3. */
  4. // /ware/purchase/merge
  5. @PostMapping("/merge")
  6. public R merge(@RequestBody MergeVo vo) {
  7. boolean mergePurchase = false;
  8. mergePurchase = purchaseService.mergePurchase(vo);
  9. if (mergePurchase) {
  10. return R.ok();
  11. }
  12. return R.error(404, "所选采购单状态不合法");
  13. }
  1. /**
  2. * 合并采购需求到采购单;若指定采购单,则合并到指定采购单,反之新建采购单合并
  3. * @param vo
  4. */
  5. @Transactional
  6. @Override
  7. public boolean mergePurchase (MergeVo vo) {
  8. Long purchaseId = vo.getPurchaseId(); // 获取前端传送的采购单Id
  9. if (purchaseId == null) { //没有指定采购单,那么需要新建一个采购单
  10. PurchaseEntity purchaseEntity = new PurchaseEntity();
  11. purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode()); // 设置采购单状态 采购单状态使用一个枚举类
  12. purchaseEntity.setCreateTime(new Date()); // 设置新建时间
  13. purchaseEntity.setUpdateTime(new Date()); // 设置修改时间
  14. this.save(purchaseEntity);
  15. purchaseId = purchaseEntity.getId();
  16. }
  17. // TODO 确认采购单的状态是0或者1才可以合并
  18. Integer status = this.getById(purchaseId).getStatus();// 获取当前采购单的状态
  19. if (status < WareConstant.PurchaseStatusEnum.RECEIVE.getCode()) { // 只有当采购单的状态是新建 或 已分配时,才能够合并采购计划
  20. List<Long> purchaseDetailIds = vo.getItems(); // 获取需要合并到采购单的采购需求id
  21. Long finalPurchaseId = purchaseId; // 采购单Id
  22. // 更新每个id对应的采购计划的属性
  23. List<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailIds.stream().map(item -> {
  24. PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();
  25. purchaseDetailEntity.setId(item);
  26. purchaseDetailEntity.setPurchaseId(finalPurchaseId); // 更新采购计划属于哪个采购单
  27. purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode()); // 更新状态
  28. return purchaseDetailEntity;
  29. }).collect(Collectors.toList());
  30. purchaseDetailService.updateBatchById(purchaseDetailEntities); // 批量更新采购计划
  31. // 更新采购单的更新时间
  32. PurchaseEntity purchaseEntity = new PurchaseEntity();
  33. purchaseEntity.setId(purchaseId);
  34. purchaseEntity.setUpdateTime(new Date());
  35. this.updateById(purchaseEntity);
  36. return true;
  37. }
  38. return false;
  39. }

3.4 完成采购

完成采购后,采购需求将会添加到库存中去。 https://easydoc.net/s/78237135/ZUqEdvA4/cTQHGXbK
整个业务逻辑分为三个步骤:

  1. 改变采购项的状态
  2. 改变采购单的状态(如果采购需求项存在异常,那么采购单异常)
  3. 将采购成功的采购需求入库

新建Vo类型class,用于接收前端数据

  1. @Data
  2. public class PurchaseItemDoneVo {
  3. private Long itemId; //采购需求Id
  4. private Integer status; // 采需求状态
  5. private String reason; // 采购失败原因
  6. }

Mybatis配置类 (把MapperScan跟 @EnableTransactionManagement【开启事务支持】放到这边来,其实无所谓) 这里分页配置我是新版配置,跟视频里面的不一样,参考官网

  1. @Configuration
  2. @EnableTransactionManagement
  3. @MapperScan("com.atguigu.gulimall.gulimallware.dao")
  4. public class WareMyBatisConfig {
  5. @Bean
  6. public MybatisPlusInterceptor mybatisPlusInterceptor() {
  7. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  8. PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
  9. // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
  10. paginationInnerInterceptor.setOverflow(true);
  11. // 设置最大单页限制数量,默认 500 条,-1 不受限制
  12. paginationInnerInterceptor.setMaxLimit(1000L);
  13. // optimizeJoin字段设置(默认为true)是否生成 countSql 优化掉 join 现在只支持 left join
  14. paginationInnerInterceptor.setOptimizeJoin(true);
  15. interceptor.addInnerInterceptor(paginationInnerInterceptor);
  16. return interceptor;
  17. }
  18. }
  1. /**
  2. * 完成采购单
  3. */
  4. @PostMapping("/done")
  5. public R finish(@RequestBody PurchaseDoneVo doneVo) {
  6. purchaseService.done(doneVo);
  7. return R.ok();
  8. }
  1. @Autowired
  2. WareSkuService wareSkuService;
  3. /**
  4. * 完成采购单
  5. */
  6. @Override
  7. public void done(PurchaseDoneVo doneVo) {
  8. // 1、改变采购需求状态
  9. Boolean flag = true; // 记录采购项是否都正常
  10. List<PurchaseItemDoneVo> items = doneVo.getItems(); // 获取采购项
  11. List<PurchaseDetailEntity> updates = new ArrayList<>();
  12. for (PurchaseItemDoneVo item : items) {
  13. PurchaseDetailEntity detailEntity = new PurchaseDetailEntity();
  14. if (item.getStatus() == WareConstant.PurchaseDetailStatusEnum.FAIL.getCode()) {
  15. flag = false;
  16. } else { // 3、采购项采购成功,将成功采购的入库
  17. // 通过id查出当前采购项的详细信息
  18. PurchaseDetailEntity byId = purchaseDetailService.getById(item.getItemId());
  19. // 将当前sku的skuId 仓库Id 以及采购数量传过去
  20. wareSkuService.addStock(byId.getSkuId(), byId.getWareId(), byId.getSkuNum());
  21. }
  22. // PurchaseDetailEntity实体类封装需要改变的status
  23. detailEntity.setStatus(item.getStatus());
  24. detailEntity.setId(item.getItemId());
  25. updates.add(detailEntity);
  26. }
  27. purchaseDetailService.updateBatchById(updates);
  28. // 2、改变采购单状态
  29. Long purchaseId = doneVo.getId();
  30. PurchaseEntity purchase = new PurchaseEntity();
  31. purchase.setId(purchaseId);
  32. purchase.setStatus(flag ? WareConstant.PurchaseStatusEnum.FINISH.getCode() : WareConstant.PurchaseStatusEnum.ERROR.getCode());
  33. purchase.setUpdateTime(new Date());
  34. this.updateById(purchase);
  35. }

在讲采购项入库的操作中,需要根据skuId获取到skuName,因此需要远程调用gulimall-product服务。主启动类不要忘记加上@EnableFeignClients注解。
这里远程调用有两种写法:
1. 让所有请求过网关:
@FeignClient(“gulimall-gateway”):给gulimall-gateway所在的机器发请求
@RequestMapping(“/api/gulimallproduct/skuinfo/info/{skuId}”)
2. 不过网关直接给后台服务发请求
@FeignClient(“gulimall-product”)
@RequestMapping(“/gulimallproduct/skuinfo/info/{skuId}”)

  1. package com.atguigu.gulimall.gulimallware.feign;
  2. @FeignClient("gulimall-product")
  3. //@FeignClient("gulimall-gateway")
  4. public interface ProductFeignService {
  5. // @RequestMapping("/api/gulimallproduct/skuinfo/info/{skuId}")
  6. @RequestMapping("/gulimallproduct/skuinfo/info/{skuId}")
  7. //@RequiresPermissions("gulimallproduct:skuinfo:info")
  8. public R info(@PathVariable("skuId") Long skuId);
  9. }

在远程调用过程中,可能会出现异常,如果单纯是因为skuName失败就回滚整个事务,不太划算。这里可以采用try-catch捕获异常。也可以使用其他方法(服务降级,准备一个兜底方法),将会在高级篇讲解。

  1. @Autowired
  2. WareSkuDao wareSkuDao;
  3. @Autowired
  4. ProductFeignService productFeignService;
  5. /**
  6. * 添加sku库存
  7. *
  8. * @param skuId
  9. * @param wareId
  10. * @param skuNum
  11. */
  12. @Transactional
  13. @Override
  14. public void addStock(Long skuId, Long wareId, Integer skuNum) {
  15. // 1、判断是否存在这个库存记录,没有就是新增操作
  16. List<WareSkuEntity> wareSkuEntities = wareSkuDao.selectList(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));
  17. if (CollectionUtils.isEmpty(wareSkuEntities)) {
  18. WareSkuEntity wareSkuEntity = new WareSkuEntity();
  19. wareSkuEntity.setSkuId(skuId);
  20. wareSkuEntity.setWareId(wareId);
  21. wareSkuEntity.setStock(skuNum);
  22. wareSkuEntity.setStockLocked(0);
  23. // TODO 这里应该远程查询sku的名字,如果失败整个事务不需要回滚
  24. // 方式1:自己catch异常
  25. // TODO 还可用什么办法让异常出现以后不会滚? 高级
  26. try {
  27. R info = productFeignService.info(skuId);
  28. if (info.getCode() == 0) {
  29. Map<String, Object> map = (Map<String, Object>) info.get("skuInfo");
  30. wareSkuEntity.setSkuName(map.get("skuName").toString());
  31. }
  32. }catch (Exception e) {
  33. }
  34. wareSkuDao.insert(wareSkuEntity);
  35. }
  36. else {
  37. wareSkuDao.addStock(skuId, wareId, skuNum);
  38. }
  39. }

四、商品维护-SPU管理

4.1 解决规格维护不显示

image.png
点击spu的规格的时候就直接跳转到了400页面。这是因为gulimall-admin的sys-menu表里面没有规格的目录信息
image.png
我们添加上去即可
image.png

4.2 获取spu规格

https://easydoc.net/s/78237135/ZUqEdvA4/GhhJhkg7 api文档

  1. @Autowired
  2. private ProductAttrValueService productAttrValueService;
  3. /**
  4. * 按spuId查出spu的规格属性 pms_product_attr_value
  5. */
  6. // /product/attr/base/listforspu/{spuId}
  7. @GetMapping("/base/listforspu/{spuId}")
  8. public R baseAttrListForSpu(@PathVariable("spuId") Long spuId) {
  9. List<ProductAttrValueEntity> entities = productAttrValueService.baseAttrListForSpu(spuId); // 通过spuId查找spu对应的所有属性
  10. return R.ok().put("data", entities);
  11. }

声明&实现

  1. /**
  2. * 通过spuId查询spu对应的所有属性
  3. * @param spuId
  4. */
  5. @Override
  6. public List<ProductAttrValueEntity> baseAttrListForSpu(Long spuId) {
  7. List<ProductAttrValueEntity> entities = this.baseMapper.selectList(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
  8. return entities;
  9. }

4.3 修改spu商品规格

https://easydoc.net/s/78237135/ZUqEdvA4/GhnJ0L85 api文档
修改spu商品规格,可以直接把spuId对应的所有属性删除后,再将前端发送过来的属性添加即可。

  1. /**
  2. * 根据spuId修改对应商品规格
  3. */
  4. // /product/attr/update/{spuId}
  5. @PostMapping("/update/{spuId}")
  6. //@RequiresPermissions("gulimallproduct:attr:update")
  7. public R updateSpuAttr(@PathVariable("spuId") Long spuId, @RequestBody List<ProductAttrValueEntity> entities){
  8. productAttrValueService.updateSpuAttr(spuId, entities);
  9. return R.ok();
  10. }
  1. /**
  2. * 更新spuId对应的所有属性
  3. * @param spuId
  4. * @param entities
  5. */
  6. @Transactional
  7. @Override
  8. public void updateSpuAttr(Long spuId, List<ProductAttrValueEntity> entities) {
  9. // 1、删除spuId之前对应的所有属性
  10. this.baseMapper.delete(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));
  11. // 2、更新属性,其实就是批量插入
  12. List<ProductAttrValueEntity> productAttrValueEntities = entities.stream().map(item -> {
  13. item.setSpuId(spuId);
  14. return item;
  15. }).collect(Collectors.toList());
  16. this.saveBatch(productAttrValueEntities);
  17. }