企业网站建设一般要素,网站建设的图片,2008系统怎么搭建多个网站,怎么用电脑给域名做网站目录 1.SPU和SKU概念
2.表的关系理解
3.导入前端代码
4.完善后端接口
5.属性分组详情
6.规格参数详情
7. 销售属性详情
8.分组与属性关联
9.发布商品
10.仓库服务 1.SPU和SKU概念 SPU#xff1a;standard product unit(标准化产品单元)#xff1a;是商品信息聚合的…目录 1.SPU和SKU概念
2.表的关系理解
3.导入前端代码
4.完善后端接口
5.属性分组详情
6.规格参数详情
7. 销售属性详情
8.分组与属性关联
9.发布商品
10.仓库服务 1.SPU和SKU概念 SPUstandard product unit(标准化产品单元)是商品信息聚合的最小单位是一组可复用、易检索的标准化信息的集合该集合描述了一个产品的特性。如iphone13是SPU它是一个产品的集合 SKUstock keeping unit(库存量单位)库存进出计量的基本单元可以是件/盒/托盘等单位。 SKU是对于大型连锁超市DC配送中心物流管理的一个必要的方法。现在已经被引申为产品统一编号的简称每种产品对应有唯一的SKU号。如iphone13ProMax 1T 蓝色 是SKU 包子店中肉包子是SKU素包子是SKU水煎包是SKU… 规格参数和销售属性
像这里的商品介绍规格与包装都是属于SPU的属性。它们都属于是规格参数 像版本颜色等都属是SKU的销售属性 2.表的关系理解
属性关系-规格参数-销售属性-三级分类 关联关系 每个三级分类下有各自的属性分组表通过id和catelogid关联能查出每个分类下的属性分组 属性分组表和属性表通过一个属性属性关联表进行关联能查出每个属性分组下的属性 最终这样的关系我们可以查出每个分类的属性分组和每个属性分组对应的属性 通过思维导图来理解 手机是一级分类它下面又有属性组每个属性组又有各自的属性 SPU-SKU属性表 商品属性表和属性表通过attrid和id进行关联能查出每个spu的属性 sku销售属性表是为了表示spu下不同sku比如1号spu在此表有两个sku这两个sku有不同的销售属性是通过和属性表关联获取的 通过思维导图来理解 像网络、像素一般是固定不可选的所以是SPU属性 而内存、容量、颜色等可选的就为SKU销售属性 3.导入前端代码
重新执行“sys_menus.sql”完善菜单 正常我们是在系统管理里自定义添加步骤都是一样的其实在前端页面添加就是把数据提交到mall_admin表中,这里我们直接把提供的sql语句导入即可 如下结果 实现点击菜单的左边能够实现在右边展示数据 这个页面就是三级分类和一个表格显示在一块对吧属于是父子组件交互 前端不具体写了我们直接导入代码效果如下 4.完善后端接口
什么是开发接口 开发接口就是开发Controller、service、dao 在线接口文档如下 03、获取分类属性分组 - 谷粒商城谷粒商城 - 03、获取分类属性分组http GET /product/attrgroup/list/{catelogId},技术团队的文档管理平台接口文档工具支持在线接口调试一键生成API文档适合编写接口文档、产品文档、使用手册https://easydoc.net/s/78237135/ZUqEdvA4/OXTgKobR 别人告诉你需要什么功能需要返回什么样的数据你就通过接口的形式把他们呢实现出来即可 以后工作了也是这种形式主要是开发接口为多前端其实不用写太多能看懂即可 5.属性分组详情
显示属性分组
controller RequestMapping(/list/{catelogId})public R list(RequestParam MapString, Object params,PathVariable(catelogId) Long catelogId){
// PageUtils page attrGroupService.queryPage(params);PageUtils page attrGroupService.queryPage(params, catelogId);return R.ok().put(page, page);}service 这里注意前端有两个查询按钮 查询和查询全部 这两个都要有模糊查询的功能 PageUtils queryPage(MapString, Object params, Long catelogId);Override
public PageUtils queryPage(MapString, Object params, Long catelogId) {//多条件查询String key (String) params.get(key);QueryWrapperAttrGroupEntity wrapper new QueryWrapper();if (!StringUtils.isEmpty(key)) {wrapper.and((obj) - {obj.eq(attr_group_id,key).or().like(attr_group_name,key);});}if (catelogId 0) {//如果是默认的是查全部的一级分类IPageAttrGroupEntity page this.page(new QueryAttrGroupEntity().getPage(params),wrapper);return new PageUtils(page);} else {wrapper.eq(catelog_id, catelogId);IPageAttrGroupEntity page this.page(new QueryAttrGroupEntity().getPage(params), wrapper);return new PageUtils(page);}
}属性分组回显 这一部分主要是做属性分组的数据回显的 controller
/*** 信息*/
RequestMapping(/info/{attrId})
public R info(PathVariable(attrId) Long attrId){AttrEntity attr attrService.getById(attrId);Long catelogId attr.getCatelogId();Long[] path categoryService.findCatelogPath(catelogId);attr.setCatelogPath(path);return R.ok().put(attr, attr);
}service 获取分类路径id 通过递归操作完成 过程 给一个分类id不断的查它的父类id直到查不到为止最后把查询到的id到放到一个集合里 怎样写好递归 确定参数值和返回值确定终止条件递归逻辑三者缺一不可 //找到catelogId的完整路径:[父/子/孙]
Override
public Long[] findCatelogPath(Long catelogId) {ArrayListLong list new ArrayList();ListLong parentPath findParentPath(catelogId, list);//1.确定递归参数和返回值Collections.reverse(parentPath);return (Long[]) list.toArray(new Long[parentPath.size()]);
}private ListLong findParentPath(Long catelogId,ArrayListLong list){//3.递归逻辑list.add(catelogId);CategoryEntity entity this.getById(catelogId);if (entity.getParentCid()!0){//2.递归终止条件findParentPath(entity.getParentCid(),list);}return list;
}测试 返回属性的父路径id 6.规格参数详情
接口如下 什么是规格参数 保存规格参数
/*** 保存*/
RequestMapping(/save)
public R save(RequestBody AttrVo vo){attrService.saveAttr(vo);return R.ok();
}service 这里注意因为添加规格参数的时候会有选择属性组因为属性组和属性是通过关联关系表连接的所以要有级联操作。 在往pms_attr表插入数据的时候pms_attr_group_relation也要插入 小bug这里有个注意点当添加规格参数的时候如果没有指定规格参数所属分组那么就不应该在关联表中保存关联关系 Override
public void saveAttr(AttrVo attr) {AttrEntity attrEntity new AttrEntity();//1.将前端接收数据的对象vo赋值给attrEntity对象从而更新数据库BeanUtils.copyProperties(attr, attrEntity);this.save(attrEntity);if (attr.getAttrType() ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() attr.getAttrGroupId() ! null) {//2.保存关联关系//因为属性组和属性是通过关联关系表连接的AttrAttrgroupRelationEntity relationEntity new AttrAttrgroupRelationEntity();relationEntity.setAttrGroupId(attr.getAttrGroupId());relationEntity.setAttrId(attrEntity.getAttrId());relationService.save(relationEntity);}}显示规格参数
/*** 显示规格参数*/
GetMapping(/base/list/{catelogId})
public R baseAttrList(RequestParam MapString, Object params,PathVariable(catelogId) Integer catelogId) {PageUtils page attrService.queryBaseAttrPage(params, catelogId);return R.ok().put(page, page);
}service
//分页查询规格参数
Override
public PageUtils queryBaseAttrPage(MapString, Object params, Integer catelogId) {QueryWrapperAttrEntity wrapper new QueryWrapper();if (catelogId ! 0) {//如果不是一级分类那么查询的时候加上where catelog_id ?wrapper.eq(catelog_id, catelogId);}//多条件模糊查询//搜索框里的key不但可以对catelog_id进行模糊查询对attr_name也模糊查询String key (String) params.get(key);if (!StringUtils.isEmpty(key)) {wrapper.eq(attr_id, key).or().like(attr_name, key);}//多条件分页查询IPageAttrEntity page this.page(new QueryAttrEntity().getPage(params),wrapper);PageUtils pageUtils new PageUtils(page);return pageUtils;
}测试 这些属性的分类和所属分组怎么查呢 规格参数表pms_attr中有所属分类的信息可以直接调用分类的service进行查询 那分组信息怎么查询呢规格参数表中没有所属分类相关的信息… 这里我们就要借助第三张表属性和分组表pms_attr_attrgroup_relation进行查询 通过规格参数表pms_attr获得attr_id之后在调用属性和分组表的service获得属性和分组表的实体类从而获得该属性的分组 下面通过stream流的方式通过map给list集合中的每一项做映射给新实体类AttrRespVo赋值最后返回AttrRespVo 小bug这里显示规格参数的时候会显示规格。参数对应的分组、分类那么如果它们查出对象分组id或分类id为空那就不设置名字if (attrId ! null attrId.getAttrGroupId() ! null) {…} //分页查询规格参数
Override
public PageUtils queryBaseAttrPage(MapString, Object params, String type, Integer catelogId) {QueryWrapperAttrEntity wrapper new QueryWrapperAttrEntity().eq(attr_type, base.equalsIgnoreCase(type) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());if (catelogId ! 0) {//如果不是一级分类那么查询的时候加上where catelog_id ?//IgnoreCase忽略大小写wrapper.eq(catelog_id, catelogId);}//多条件模糊查询//搜索框里的key不但可以对catelog_id进行模糊查询对attr_name也模糊查询String key (String) params.get(key);if (!StringUtils.isEmpty(key)) {wrapper.eq(attr_id, key).or().like(attr_name, key);}//多条件分页查询IPageAttrEntity page this.page(new QueryAttrEntity().getPage(params),wrapper);PageUtils pageUtils new PageUtils(page);ListAttrEntity list page.getRecords();// .map()这个方法是对被筛选过后的流进行映射一般是对属性进行赋值。ListAttrRespVo resultList list.stream().map(item - {AttrRespVo attrRespvo new AttrRespVo();BeanUtils.copyProperties(item, attrRespvo);//设置分类和分组的名字if (base.equalsIgnoreCase(type)) {AttrAttrgroupRelationEntity attrId relationService.getOne(new QueryWrapperAttrAttrgroupRelationEntity().eq(attr_id, item.getAttrId()));if (attrId ! null attrId.getAttrGroupId() ! null) {//attrgroupRelationEntity.getAttrGroupId()也可以这里可以直接放进去对象AttrGroupEntity attrGroupEntity attrGroupService.getById(attrId.getAttrGroupId());attrRespvo.setGroupName(attrGroupEntity.getAttrGroupName());}}CategoryEntity categoryEntity categoryService.getById(item.getCatelogId());if (categoryEntity ! null) {attrRespvo.setCatelogName(categoryEntity.getName());}//返回最后的封装结果return attrRespvo;}).collect(Collectors.toList());//返回的结果是一个集合pageUtils.setList(resultList);// 返回分页后的集合对象return pageUtils;
}AttrRespVo
Data
public class AttrRespVo extends AttrVo {private String catelogName;private String groupName;
}测试 规格参数回显 可以看出所属分类和分组都是由这条请求查询的那么我们改这个接口功能就行 相当于在原来查询基础上返回分类路径信息分组信息 controller
/*** 信息*/
RequestMapping(/info/{attrId})
public R info(PathVariable(attrId) Long attrId) {AttrRespVo respVo attrService.getAttrInfo(attrId);return R.ok().put(attr, respVo);
}service
Override
public AttrRespVo getAttrInfo(Long attrId) {AttrRespVo respVo new AttrRespVo();AttrEntity attrEntity this.getById(attrId);BeanUtils.copyProperties(attrEntity, respVo);/*** 设置分组信息*/AttrAttrgroupRelationEntity attrgroupRelationEntity relationService.getOne(new QueryWrapperAttrAttrgroupRelationEntity().eq(attr_id, attrEntity.getAttrId()));if (attrgroupRelationEntity ! null){respVo.setAttrGroupId(attrgroupRelationEntity.getAttrGroupId());Long attrGroupId attrgroupRelationEntity.getAttrGroupId();AttrGroupEntity attrGroupEntity attrGroupService.getById(attrGroupId);if (attrGroupEntity ! null) {respVo.setGroupName(attrGroupEntity.getAttrGroupName());}}/*** 设置分类信息*/Long catelogId attrEntity.getCatelogId();//有了分类的完整路径接下来就设置分类名字Long[] catelogPath categoryService.findCatelogPath(catelogId);respVo.setCatelogPath(catelogPath);//获得分类名字CategoryEntity categoryEntity categoryService.getById(catelogId);if (categoryEntity ! null) {respVo.setCatelogName(categoryEntity.getName());}return respVo;
}测试 修改Or增加 提交修改分类和分组是无效的 更改用的还是默认的update方法所以我们改update接口 controller
/*** 修改*/
RequestMapping(/update)
public R update(RequestBody AttrVo attr) {attrService.updateAttr(attr);return R.ok();
}service 这里做了优化对于规格参数中没有所属分组的如果指定了不在是修改而是添加 怎么判断规格参数有没有所属分组呢 拿attr_id去pms_attr_attrgroup_relation表中查询如果改attr_id存在与该表那就修改关联关系 如果没有数据那么就在此表添加数据 Transactional
Override
public void updateAttr(AttrVo attr) {AttrEntity attrEntity new AttrEntity();BeanUtils.copyProperties(attr, attrEntity);this.updateById(attrEntity);//修改分组关联AttrAttrgroupRelationEntity attrAttrgroupRelationEntity new AttrAttrgroupRelationEntity();attrAttrgroupRelationEntity.setAttrGroupId(attr.getAttrGroupId());attrAttrgroupRelationEntity.setAttrId(attr.getAttrId());//统计attr_id的关联属性,如果没有初始分组,则进行添加操作;有则进行修改操作Integer count relation.selectCount(new QueryWrapperAttrAttrgroupRelationEntity().eq(attr_id, attr.getAttrId()));if (count 0) {relation.update(attrAttrgroupRelationEntity, new UpdateWrapperAttrAttrgroupRelationEntity().eq(attr_id, attr.getAttrId()));} else {relation.insert(attrAttrgroupRelationEntity);}
}spu规格维护 出现400页面在数据库添加 INSERT INTO sys_menu (menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (76, 37, 规格维护, product/attrupdate, , 2, log, 0);更新index.js哪里更新找老师的源码controller
PostMapping(/update/{spuId})
public R updateSpuAttr(PathVariable(spuId) Long spuId,RequestBody ListProductAttrValueEntity entities){productAttrValueService.updateSpuAttr(spuId,entities);return R.ok();
}impl 这里的修改其实是先把原来的spu_id下的属性都删除掉 之后在把前端传来的属性集合进行批量保存 Transactional(rollbackFor Exception.class)
Override
public void updateSpuAttr(Long spuId, ListProductAttrValueEntity entities) {//1、删除spuId之前对应的所有属性this.baseMapper.delete(new QueryWrapperProductAttrValueEntity().eq(spu_id,spuId));//2、添加商品规格信息ListProductAttrValueEntity collect entities.stream().map(item - {item.setSpuId(spuId);return item;}).collect(Collectors.toList());//批量新增this.saveBatch(collect);
}7. 销售属性详情
显示销售属性 如图http://localhost:88/api/product/attr/sale/list/0?t1660181297434page1limit10key这个接口有问题 所以我们就去后端改这个接口即可 controller 规格参数和销售参数的区别在于type的值type为 1是规格参数type为0是销售参数 这里采用一个方法当两个来用 GetMapping(/{attrType}/list/{catelogId})
public R baseAttrList(RequestParam MapString, Object params,PathVariable(attrType) String type,PathVariable(catelogId) Integer catelogId) {PageUtils page attrService.queryBaseAttrPage(params, type, catelogId);return R.ok().put(page, page);
}service 在原来对规格参数的基础上加了限制条件如果是规格参数那就是WHERE attr_type 1,否则就是WHERE attr_type 0 下面的逻辑和查询规格参数一致都要模糊查询 这里为了使代码更通用1和0的值我们写一个常量来控制如过后期换值了我们直接更改常量的值即可 ProductConstant
package com.xxh.common.constant;public class ProductConstant {public enum AttrEnum{ATTR_TYPE_BASE(1,基本属性),ATTR_TYPE_SALE(0,销售属性);private int code;private String msg;AttrEnum(int code,String msg){this.code code;this.msg msg;}public int getCode(){return code;}public String getMsg(){return msg;}}
}在原来对规格参数的基础上加了限制条件如果是规格参数那就是WHERE attr_type 1,否则就是WHERE attr_type 0 Overridepublic PageUtils queryBaseAttrPage(MapString, Object params, String type, Integer catelogId) {QueryWrapperAttrEntity wrapper new QueryWrapperAttrEntity().eq(attr_type, base.equalsIgnoreCase(type) ? ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() : ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());if (catelogId ! 0) {//如果不是一级分类那么查询的时候加上where catelog_id ?//IgnoreCase忽略大小写wrapper.eq(catelog_id, catelogId);}//多条件模糊查询//搜索框里的key不但可以对catelog_id进行模糊查询对attr_name也模糊查询String key (String) params.get(key);if (!StringUtils.isEmpty(key)) {wrapper.eq(attr_id, key).or().like(attr_name, key);}//多条件分页查询IPageAttrEntity page this.page(new QueryAttrEntity().getPage(params),wrapper);PageUtils pageUtils new PageUtils(page);ListAttrEntity list page.getRecords();
// .map()这个方法是对被筛选过后的流进行映射一般是对属性进行赋值。ListAttrRespVo resultList list.stream().map(item - {AttrRespVo attrRespvo new AttrRespVo();BeanUtils.copyProperties(item, attrRespvo);AttrAttrgroupRelationEntity attrgroupRelationEntity relationService.getOne(new QueryWrapperAttrAttrgroupRelationEntity().eq(attr_id, item.getAttrId()));if (attrgroupRelationEntity ! null) {//attrgroupRelationEntity.getAttrGroupId()也可以这里可以直接放进去对象AttrGroupEntity attrGroupEntity attrGroupService.getById(attrgroupRelationEntity);attrRespvo.setGroupName(attrGroupEntity.getAttrGroupName());}CategoryEntity categoryEntity categoryService.getById(item.getCatelogId());if (categoryEntity ! null) {attrRespvo.setCatelogName(categoryEntity.getName());}//返回最后的封装结果return attrRespvo;}).collect(Collectors.toList());//返回的结果是一个集合pageUtils.setList(resultList);// 返回分页后的集合对象return pageUtils;}销售属性回显 可以看到销售属性回显是不需要所属分组的 但是销售属性和规格参数用的是同一个回显方法我们也进行更改只有是规格参数的时候才进行分组回显 在原分组回显的逻辑上加上判断后面逻辑不变 if (attrEntity.getAttrType() ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {...
}修改销售属性 销售属性和规格参数用的是同一个修改方法销售属性进行修改时会对关联表进行一个级联更新但销售属性不需要 所以也在对关联表级联更新的时候进行判断只有销售属性修改的时候才进行级联更新 if (attrEntity.getAttrType() ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {...
}保存销售属性 销售属性和规格参数用的是同一个保存方法销售属性进行保存时会对关联表进行一个级联保存但销售属性不需要 所以也在对关联表级联保存的时候进行判断只有销售属性保存的时候才进行级联保存 if (attrEntity.getAttrType() ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {...
}8.分组与属性关联
显示属性 这里其实就是一个分布查询流程如下 点击分组属性的时候获取到分组id拿分组id去关联表查分组id对应的attr_id拿attr_id去pms_attr表中获取属性controller
/*** 3.获取属性分组的关联的所有属性*/
RequestMapping(/{attrgroupId}/attr/relation)
public R attrRelation(PathVariable(attrgroupId) Long attrgroupId) {ListAttrEntity entities attrService.getRelationAttr(attrgroupId);return R.ok().put(data, entities);
}service
Override
public ListAttrEntity getRelationAttr(Long attrgroupId) {//分布查询第一步去关联表中查出所有的组和属性idListAttrAttrgroupRelationEntity entities relationService.list(new QueryWrapperAttrAttrgroupRelationEntity().eq(attr_group_id,attrgroupId));//第二收集属性idListLong attrIds entities.stream().map((attr) - {return attr.getAttrId();}).collect(Collectors.toList());ListAttrEntity list this.listByIds(attrIds);return list;
}测试 移除属性 这里为了方便我们直接写一个批量删除的接口 controller /product/attrgroup/attr/relation/deletepost请求会带来json数据要封装成自定义对象vos需要RequestBody注解意思就是将请求体中的数据封装成vos/*** 4.移除属性分组和属性的关系*/
PostMapping(/attr/relation/delete)
public R deleteRelation(RequestBody AttrGroupRelationVo[] vos) {attrService.deleteRelation(vos);return R.ok();
}service
Override
public void deleteRelation(AttrGroupRelationVo[] vos) {ListAttrAttrgroupRelationEntity entities Arrays.asList(vos).stream().map((item) - {AttrAttrgroupRelationEntity entity new AttrAttrgroupRelationEntity();BeanUtils.copyProperties(item, entity);return entity;}).collect(Collectors.toList());relation.deleteBatchRelation(entities);
}mapper
void deleteBatchRelation(Param(entities) ListAttrAttrgroupRelationEntity entities);delete iddeleteBatchRelationDELETE FROM pms_attr_attrgroup_relation whereforeach collectionentities itemitem separatorOR(attr_id #{item.attrId} AND attr_group_id #{item.attrGroupId})/foreach/delete查询分组未关联的属性 controller
/*** 5.获取属性分组没有关联的所有属性* /product/attrgroup/{attrgroupId}/noattr/relation*/
RequestMapping(/{attrgroupId}/noattr/relation)
public R attrNoRelation(RequestParam MapString, Object params,PathVariable(attrgroupId) Long attrgroupId) {PageUtils page attrService.getNoRelationAttr(params,attrgroupId);return R.ok().put(page, page);
}service 认真看注释认真理解还是很绕的 查询分组未关联的数据三步 获得当前分类下的所有分组获得这些分组下所有已添加的属性添加新属性时移除这些已添加的属性Override
public PageUtils getNoRelationAttr(MapString, Object params, Long attrgroupId) {/*** 1.当前分组只能关联自己所属的分类里面的所有属性*/AttrGroupEntity attrGroupEntity attrGroupService.getById(attrgroupId);Long catelogId attrGroupEntity.getCatelogId();/*** 2 .当前分组只能引用别的分组没有引用的属性* 2.1 当前分类下的所有分组* 2.2 这些分组关联的属性* 2.3 从当前分类的所有属性中移除这些属性*//*** 2.1 当前分类下的所有分组。收集到他们的组id*/ListAttrGroupEntity group attrGroupService.list(new QueryWrapperAttrGroupEntity().eq(catelog_id, catelogId));ListLong collectGroupIds group.stream().map((item) - {return item.getAttrGroupId();}).collect(Collectors.toList());/*** 2.2 收集到分组的所有属性* 1拿着上一步收集到的组id到关系表中查找关系表实体类对象* 2通过关系表实体类对象获得所有分组下的所有属性id*/ListAttrAttrgroupRelationEntity groupId relationService.list(new QueryWrapperAttrAttrgroupRelationEntity().in(attr_group_id, collectGroupIds));ListLong attrIds groupId.stream().map((item) - {return item.getAttrId();}).collect(Collectors.toList());/*** 2.3 从当前分类的所有属性中移除这些属性并筛选出基本属性where attr_type 1*/QueryWrapperAttrEntity wrapper new QueryWrapperAttrEntity().eq(catelog_id, catelogId).eq(attr_type,ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());//如果其他分组也没关联属性那么就不加这个条件if (attrIds ! null attrIds.size() 0){wrapper.notIn(attr_id, attrIds);}/*** 分页多条件查询* where (attr_id ? or attr_name like ?)*/String key (String) params.get(key);if (!StringUtils.isEmpty(key)) {wrapper.and((w) - {w.eq(attr_id, key).or().like(attr_name, key);});}/*** page方法需要两个参数* 1.IPage对象通过工具类Query获取并通过.getPage(params)封装页面传来分页参数* 2.wrapper自己生成*/IPageAttrEntity page this.page(new QueryAttrEntity().getPage(params), wrapper);PageUtils pageUtils new PageUtils(page);return pageUtils;
}注意非空判断 测试 给销售属性绑定分组把9号属性绑定给1号分组 查询分组未关联的属性 添加属性关联 常规的调用注意点是saveBatch传的参数是数据对应的实体类 我们想传其他vo时需要对这个方法进行一个重写 最后也是通过把vo的值赋给对应实体类在调用相应批量保存 controller
/*** 6.添加属性与分组关联关系* /product/attrgroup/attr/relation*/
PostMapping(/attr/relation)
public R addRelation(RequestBody ListAttrGroupRelationVo vos) {relationService.saveBatch(vos);return R.ok();
}service
Override
public void saveBatch(ListAttrGroupRelationVo vos) {ListAttrAttrgroupRelationEntity collect vos.stream().map((item) - {AttrAttrgroupRelationEntity relationEntity new AttrAttrgroupRelationEntity();BeanUtils.copyProperties(item, relationEntity);return relationEntity;}).collect(Collectors.toList());this.saveBatch(collect);
}9.发布商品
调试会员等级接口 启动会员微服务添加网关添加前端页面… 添加如下会员 获取分类关联的品牌
/*** 1.获取分类关联的品牌* /product/categorybrandrelation/brands/list*/
GetMapping(/brands/list)
public R relationBrandList(RequestParam(value catId, required true) Long catId) {ListBrandEntity vos categoryBrandRelationService.getBrandsByCatId(catId);//品牌对象集合在进行筛选赋予品牌对象id和name返回封装的vo给前端ListBrandVo collect vos.stream().map(item - {BrandVo brandVo new BrandVo();brandVo.setBrandId(item.getBrandId());brandVo.setBrandName(item.getName());return brandVo;}).collect(Collectors.toList());return R.ok().put(data,collect);
}service
Override
public ListBrandEntity getBrandsByCatId(Long catId) {//获得CategoryBrandRelationEntity集合对象ListCategoryBrandRelationEntity catelogId relationDao.selectList(new QueryWrapperCategoryBrandRelationEntity().eq(catelog_id, catId));//获得所有集合对象中brandid通过brandService查询所有品牌封装成品牌对象集合ListBrandEntity collect catelogId.stream().map(item - {Long brandId item.getBrandId();BrandEntity entity brandService.getById(brandId);return entity;}).collect(Collectors.toList());//返回品牌对象集合return collect;
}测试 开发规范 Controller:处理请求,接受和校验数据Service接受controller传来的数据,进行业务处理Controller接受service处理完的数据,封装页面指定的vo获取分类下所有分组关联属性 也就是说当我们选择手机分类时那就查出手机相关的分组信息并查出每个分组相应属性信息 Data
public class AttrGroupWithAttrsVo {/*** 分组id*/TableIdprivate Long attrGroupId;/*** 组名*/private String attrGroupName;/*** 排序*/private Integer sort;/*** 描述*/private String descript;/*** 组图标*/private String icon;/*** 所属分类id*/private Long catelogId;private ListAttrEntity attrs;
}controller
/*** 7.获取分类下所有分组关联属性* /product/attrgroup/{catelogId}/withattr*/
GetMapping(/{catelogId}/withattr)
public R getAttrGroupWithAttrs(PathVariable(catelogId) Long catelogId) {ListAttrGroupWithAttrsVo vos attrGroupService.getAttrGroupWithAttrsByCatelogId(catelogId);return R.ok().put(data,vos);
}service vo的重要性 vovalue object当相应数据需要自定义时用vo是最好的选择不需要对实体类字段进行修改 /*** 获取分类下的所有分组及属性* param catelogId* return*/Overridepublic ListAttrGroupWithAttrsVo getAttrGroupWithAttrsByCatelogId(Long catelogId) {/** 1.获取分类下的所有分组,封装成集合* 分类和组的关系在pms_group表中所以where catelog_id 即可查出分类对应的组* 由于这是mp它会得出所有的这种关系并把结果封装成集合*/ListAttrGroupEntity list this.list(new QueryWrapperAttrGroupEntity().eq(catelog_id, catelogId));/** 2.获得分组下的属性* 要第三张关联表,直接调用关联表的service即查询分组对应的属性id* 获得属性id在去调用属性表的service即可查询属性名* 以上两步前面已经写好逻辑了直接调用即可attrService.getRelationAttrgroupId*/ListAttrGroupWithAttrsVo collect list.stream().map((item) - {AttrGroupWithAttrsVo attrGroupWithAttrsVo new AttrGroupWithAttrsVo();BeanUtils.copyProperties(item, attrGroupWithAttrsVo);ListAttrEntity attrs attrService.getRelationAttr(attrGroupWithAttrsVo.getAttrGroupId());if (attrs ! null) {attrGroupWithAttrsVo.setAttrs(attrs);}return attrGroupWithAttrsVo;}).filter((attrvo) - {return attrvo.getAttrs() ! null attrvo.getAttrs().size() 0;}).collect(Collectors.toList());return collect;}测试 商品新增vo抽取 设置完属性点击保存之后取消保存复制控制台输出 在线JSON字符串转Java实体类(JavaBean、Entity)-BeJSON.com
直接解析json数据封装成实体类 这里我简单截取一个主要的Vo 此Vo包括每个步骤所携带的数据有的是单个字段有的是一个集合 逻辑不难难点是要理清逻辑注意细节 Data
public class SpuSaveVo {NotEmpty(groups {AddGroup.class})private String spuName;private String spuDescription;NotEmpty(groups {AddGroup.class})private Long catalogId;NotEmpty(groups {AddGroup.class})private Long brandId;private double weight;private int publishStatus;private ListString decript;private ListString images;private Bounds bounds;NotEmpty(groups {AddGroup.class})private ListBaseAttrs baseAttrs;NotEmpty(groups {AddGroup.class})private ListSkus skus;}商品新增业务流程分析 逻辑很简单那就是把数据保存到多张表中 因为这个Vo收集的数据很多包括每个步骤你所选择的数据 保存spu基本信息 pms_spu_info 因为所有传来的信息都在vo里所以我们把信息拷贝到对应的实体类中如果vo没有的那就可以自己赋值 表结构如下 这里的infoEntity.setCreateTime(new Date());infoEntity.setUpdateTime(new Date());是因为前端传入的是没有这两个字段的我们自己赋值即可 SpuInfoEntity infoEntity new SpuInfoEntity();
BeanUtils.copyProperties(vo, infoEntity);
infoEntity.setCreateTime(new Date());
infoEntity.setUpdateTime(new Date());
this.saveBaseInfo(infoEntity);保存spu的描述图片 pms_spu_info_desc 保存哪个数据到哪个表就注入那个service String.join()的作用是把集合中的元素通过,分割形成一个一个的字符串 ListString decript vo.getDecript();
SpuInfoDescEntity descEntity new SpuInfoDescEntity();
descEntity.setSpuId(infoEntity.getId());
descEntity.setDecript(String.join(,, decript));
spuInfoDescService.saveSpuInfoDesc(descEntity);保存spu的图片集 pms_spu_images 从vo中获取所有图片集合 调用图片service进行保存保存只需要两个点 图片id和url地址传入对象即可 ListString images vo.getImages();
imagesService.saveImages(infoEntity.getId(), images);保存spu的规格参数 pms_product_attr_value 从vo中获取所有规格参数集合 对规格参数集合进行遍历设置每项的属性 ListBaseAttrs baseAttrs vo.getBaseAttrs();
ListProductAttrValueEntity collect baseAttrs.stream().map((attr) - {ProductAttrValueEntity valueEntity new ProductAttrValueEntity();valueEntity.setAttrId(attr.getAttrId());AttrEntity id attrService.getById(attr.getAttrId());valueEntity.setAttrName(id.getAttrName());valueEntity.setAttrValue(attr.getAttrValues());valueEntity.setQuickShow(attr.getShowDesc());valueEntity.setSpuId(infoEntity.getId());return valueEntity;
}).collect(Collectors.toList());
attrValueService.saveProductAttr(collect);保存spu的积分信息 mall_sms - sms_spu_bounds
Bounds bounds vo.getBounds();
SpuBoundTo spuBoundTo new SpuBoundTo();
BeanUtils.copyProperties(bounds, spuBoundTo);
spuBoundTo.setSpuId(infoEntity.getId());
R r0 couponFeignService.saveSpuBounds(spuBoundTo);
if (r0.getCode() ! 0) {log.error(远程保存spu积分信息异常);
}
couponFeignService.saveSpuBounds(spuBoundTo);保存当前spu对应的所有sku信息
//6.1sku的基本信息;pms_sku_info
ListSkus skus vo.getSkus();
if (skus ! null skus.size() 0) {skus.forEach(item - {String defalutImg ;for (Images image : item.getImages()) {if (image.getDefaultImg() 1) {defalutImg image.getImgUrl();}}SkuInfoEntity skuInfoEntity new SkuInfoEntity();BeanUtils.copyProperties(item, skuInfoEntity);//添加vo中没有的信息skuInfoEntity.setBrandId(infoEntity.getBrandId());skuInfoEntity.setCatalogId(infoEntity.getCatalogId());skuInfoEntity.setSaleCount(0L);skuInfoEntity.setSpuId(infoEntity.getId());skuInfoEntity.setSkuDefaultImg(defalutImg);skuInfoService.saveSkuInfo(skuInfoEntity);//6.2sku图片信息;pms_sku_images//没有图片路径的无需保存Long skuId skuInfoEntity.getSkuId();ListSkuImagesEntity imageEntities item.getImages().stream().map(img - {SkuImagesEntity skuImagesEntity new SkuImagesEntity();skuImagesEntity.setSkuId(skuId);skuImagesEntity.setImgUrl(img.getImgUrl());skuImagesEntity.setDefaultImg(img.getDefaultImg());return skuImagesEntity;}).filter(entity - {return !StringUtils.isEmpty(entity.getImgUrl());}).collect(Collectors.toList());skuImagesService.saveBatch(imageEntities);//6.3sku的销售属性;pms_sku_sale_attr_valueListAttr attr item.getAttr();ListSkuSaleAttrValueEntity skuSaleAttrValueEntities attr.stream().map(a - {SkuSaleAttrValueEntity attrValueEntity new SkuSaleAttrValueEntity();BeanUtils.copyProperties(a, attrValueEntity);attrValueEntity.setSkuId(skuId);return attrValueEntity;}).collect(Collectors.toList());skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntities);//6.4sku的优惠满减信息(跨服务);SkuReductionTo skuReductionTo new SkuReductionTo();BeanUtils.copyProperties(item, skuReductionTo);skuReductionTo.setSkuId(skuId);if (skuReductionTo.getFullCount() 0 || skuReductionTo.getFullPrice().compareTo(new BigDecimal(0)) 1) {R r1 couponFeignService.saveSkuReduction(skuReductionTo);if (r1.getCode() ! 0) {log.error(远程保存spu积分信息异常);}}});
}测试 检索功能 也就是多条件分页查询很常见的功能spu检索 /*** 列表*/
RequestMapping(/list)
public R list(RequestParam MapString, Object params){PageUtils page spuInfoService.queryPageByCondition(params);return R.ok().put(page, page);
}service
Override
public PageUtils queryPageByCondition(MapString, Object params) {QueryWrapperSpuInfoEntity queryWrapper new QueryWrapper();String key (String) params.get(key);if (!StringUtils.isEmpty(key)) {//等价sql: status1 and (id1 or spu_name like xxx)queryWrapper.and((w) - {w.eq(id, key).or().like(spu_name, key);});}String status (String) params.get(status);if (!StringUtils.isEmpty(status)) {queryWrapper.eq(publish_status, status);}String brandId (String) params.get(brandId);if (!StringUtils.isEmpty(brandId) !0.equalsIgnoreCase(brandId)) {queryWrapper.eq(brand_id, brandId);}String catelogId (String) params.get(catelogId);if (!StringUtils.isEmpty(catelogId) !0.equalsIgnoreCase(catelogId)) {queryWrapper.eq(catalog_id, catelogId);}IPageSpuInfoEntity page this.page(new QuerySpuInfoEntity().getPage(params),queryWrapper);return new PageUtils(page);
}sku检索
/*** 列表*/
RequestMapping(/list)
public R list(RequestParam MapString, Object params){PageUtils page skuInfoService.queryPageByParams(params);return R.ok().put(page, page);
}service
Override
public PageUtils queryPageByParams(MapString, Object params) {QueryWrapperSkuInfoEntity queryWrapper new QueryWrapper();String key (String) params.get(key);if (!StringUtils.isEmpty(key)) {queryWrapper.and((w) - {w.eq(sku_id, key).or().like(sku_name, key);});}String catelogId (String) params.get(catelogId);if (!StringUtils.isEmpty(catelogId) !0.equalsIgnoreCase(catelogId)) {queryWrapper.eq(catalog_id, catelogId);}String brandId (String) params.get(brandId);if (!StringUtils.isEmpty(brandId) !0.equalsIgnoreCase(brandId)) {queryWrapper.eq(brand_id, brandId);}String max (String) params.get(max);if (!StringUtils.isEmpty(max)) {try {BigDecimal bigDecimal new BigDecimal(max);if (bigDecimal.compareTo(new BigDecimal(0)) 1) {queryWrapper.le(price, max);}} catch (Exception e) {}}String min (String) params.get(min);if (!StringUtils.isEmpty(min)) {queryWrapper.ge(price, min);}IPageSkuInfoEntity page this.page(new QuerySkuInfoEntity().getPage(params),queryWrapper);return new PageUtils((page));
}10.仓库服务
整合ware服务获取仓库列表 加入微服务注册中心加入网关获取仓库列表就是对仓库表的简单查询逆向生成代码以帮我们生成好只要配置好网关就可以直接显示 我们只要记住反是单表操作的逆向生成以帮我们生成好了我们能拿来直接用就像增加仓库、删除、修改都是可以直接用的 多条件分页查询
Override
public PageUtils queryPage(MapString, Object params) {QueryWrapperWareInfoEntity queryWrapper new QueryWrapper();String key (String) params.get(key);if (!StringUtils.isEmpty(key)) {queryWrapper.eq(id, key).or().like(name, key).or().like(address, key).or().like(areacode, key);}IPageWareInfoEntity page this.page(new QueryWareInfoEntity().getPage(params),queryWrapper);return new PageUtils(page);
}多条件查询都是一样的套路获得你搜索的key然后拿这个key去模糊匹配多个字段 比如这里拿你输入的key会在name、address、areacode做模糊查询条件直接通过or来拼接 查询库存 查询库存也是单表操作CRUD都帮我们做好了我们就在分页的基础上加上多条件查询即可 //多条件分页查询
Override
public PageUtils queryPage(MapString, Object params) {QueryWrapperWareSkuEntity queryWrapper new QueryWrapper();String skuId (String) params.get(skuId);if (!StringUtils.isEmpty(skuId)) {queryWrapper.eq(sku_id, skuId);}String wareId (String) params.get(wareId);if (!StringUtils.isEmpty(wareId)) {queryWrapper.eq(ware_id, wareId);}IPageWareSkuEntity page this.page(new QueryWareSkuEntity().getPage(params),queryWrapper);return new PageUtils(page);
}创建采购需求 同上都是单表操作我们只需要做采购需求的多条件分页查询 Override
public PageUtils queryPage(MapString, Object params) {QueryWrapperPurchaseDetailEntity queryWrapper new QueryWrapperPurchaseDetailEntity();String key (String)params.get(key);if(!StringUtils.isEmpty(key)){queryWrapper.and(w-{w.eq(purchase_id,key).or().eq(sku_id,key);});}String status (String)params.get(status);if(!StringUtils.isEmpty(status)) {queryWrapper.eq(status,status);}String wareId (String)params.get(wareId);if(!StringUtils.isEmpty(wareId)) {queryWrapper.eq(ware_id,wareId);}IPagePurchaseDetailEntity page this.page(new QueryPurchaseDetailEntity().getPage(params),queryWrapper);return new PageUtils(page);
}合并采购需求 创建采购单 合并请求接口 这里有两种情况如下 如果没有选中采购单那么会自动创建采购单进行合并有的话就用采购单idcontroller
/*** 合并采购单*/
PostMapping(/merge)
public R merge(RequestBody MergeVo mergeVo) {boolean flag purchaseService.mergePurchase(mergeVo);if(flag){return R.ok();}else {return R.error().put(msg,请选择新建或已分配的采购需求);}
}VO如下Data
public class MergeVo {private Long purchaseId;private ListLong items;
}impl 实际上就是创建完采购需求对象和采购单对象后点击合并这两个对象信息会发生变化整体就是做这些操作 具体的看注释这里还用到了一些枚举类的写法通过枚举类获得状态信息了解即可这里就不写了可以去看老师的源码 Transactional
Override
public boolean mergePurchase(MergeVo mergeVo) {//一、获取Vo中的信息//如果指定了采购单那就获取采购单的idLong purchaseId mergeVo.getPurchaseId();//获得采购需求的idListLong items mergeVo.getItems();//二、过滤采购需求//对采购需求id进行过滤如果采购需求处于新建或者已分配的收集成新的集合//这样做的目的是为了进行筛选如果你选中正在采购的是不会被合并的ListLong collect items.stream().filter(i - {//通过采购需求的id获取采购需求实体类PurchaseDetailEntity purchaseDetailEntity purchaseDetailService.getById(i);if (purchaseDetailEntity.getStatus() WareConstant.PurchaseDetailStatusEnum.CREATED.getCode()|| purchaseDetailEntity.getStatus() WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode()) {return true;} else {return false;}}).collect(Collectors.toList());//三、没有指定采购单逻辑和指定了的逻辑if (collect ! null collect.size() 0) {//3.1如果没有指定采购单那就自动创建一个if (purchaseId null) {PurchaseEntity purchaseEntity new PurchaseEntity();//如果是新创建的采购单创建时间更新时间状态都是没有默认值的所以这默认值我们自己来赋值purchaseEntity.setCreateTime(new Date());purchaseEntity.setUpdateTime(new Date());//这里设置采购单的状态采用的是枚举类的形式获取purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getCode());this.save(purchaseEntity);//获得自动创建的采购单idpurchaseId purchaseEntity.getId();}/** 3.2指定采购单了逻辑如下* 1.采购单id为Vo中获取的指定id* 2.设置所有的采购需求对象并收集成对象*/Long finalPurchaseId purchaseId;ListPurchaseDetailEntity collect1 collect.stream().map(i - {//获取所有的采购需求对象//更新采购需求的状态一共需要该两个点一个是采购状态一个是采购单id。设置采购需求的id是为了区分是哪一个进行了更改PurchaseDetailEntity purchaseDetailEntity purchaseDetailService.getById(i);purchaseDetailEntity.setPurchaseId(finalPurchaseId);purchaseDetailEntity.setId(i);purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getCode());return purchaseDetailEntity;}).collect(Collectors.toList());//批量更改采购需求这里是MP里的接口可直接传入对象MP会自动读取里面的IDpurchaseDetailService.updateBatchById(collect1);//四、优化时间更新为了显示的时间符合我们的样式PurchaseEntity purchaseEntity new PurchaseEntity();purchaseEntity.setId(purchaseId);purchaseEntity.setUpdateTime(new Date());//五、更新采购单return this.updateById(purchaseEntity);} else {return false;}
}领取采购单 这里我们只用写好接口的功能这个请求一般是由app来进行发送 controller
/*** 领取采购单*/
PostMapping(/received)
public R received(RequestBody ListLong ids){purchaseService.received(ids);return R.ok();
}impl 领取采购单通过接口测试工具完成请求 领取玩采购单后更改采购单状态和对应采购需求状态 采购单状态改为已领取采购需求状态改为正在采购Overridepublic void received(ListLong ids) {//1.确认当前采购单状态ListPurchaseEntity collect ids.stream().map(item - {//通过采购单id获取采购单对象PurchaseEntity purchaseEntity this.getById(item);return purchaseEntity;}).filter(id - {//对采购单对象进行过滤如果状态为新建或者已分配的留下if (id.getStatus() WareConstant.PurchaseStatusEnum.CREATED.getCode() ||id.getStatus() WareConstant.PurchaseStatusEnum.ASSIGNED.getCode()) {return true;} else {return false;}}).map(item - {//对上面收集好的在进行过滤改变采购单状态为已领取RECEIVEitem.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());//对上面收集好的在进行过滤改变采购单更新时间item.setUpdateTime(new Date());return item;}).collect(Collectors.toList());//2.批量修改改变采购单状态this.updateBatchById(collect);//3.改变采购需求中的状态if (collect ! null collect.size() 0) {collect.forEach(item - {ListPurchaseDetailEntity entities purchaseDetailService.listDetailByPurchaseId(item.getId());ListPurchaseDetailEntity detailEntities entities.stream().map(entity - {PurchaseDetailEntity purchaseDetailEntity new PurchaseDetailEntity();purchaseDetailEntity.setId(entity.getId());//将采购需求中的状态改为正在采购purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.BUYING.getCode());return purchaseDetailEntity;}).collect(Collectors.toList());purchaseDetailService.updateBatchById(detailEntities);});}}完成采购 这里我们只用写好接口的功能这个请求一般是由app来进行发送 /*** 完成采购单*/
PostMapping(/done)
public R finished(RequestBody PurchaseDoneVo doneVo){purchaseService.done(doneVo);return R.ok();
}VO如下
Data
public class PurchaseDoneVo {NonNullprivate Long id;private ListPurchaseItemDoneVo items;public PurchaseDoneVo(){}
}Data
public class PurchaseItemDoneVo {private Long itemId;private Integer status;private String reason;
}impl 完成采购主要注意有几个地方发生了变化做好逻辑的判断即可 /*** 采购完成一共三地方会发生变化* 1.采购单状态* 2.库存增加* 3.采购需求状态发生变化* param doneVo*/Overridepublic void done(PurchaseDoneVo doneVo) {//获取完成的是哪一个采购单Long id doneVo.getId();//一、初始化Boolean flag true;//获取采购单id集合ListPurchaseItemDoneVo items doneVo.getItems();//收集结果ListPurchaseDetailEntity updates new ArrayList();for (PurchaseItemDoneVo item : items) {PurchaseDetailEntity purchaseDetailEntity new PurchaseDetailEntity();if (item.getStatus() WareConstant.PurchaseDetailStatusEnum.HASERROR.getCode()) {flag false;purchaseDetailEntity.setStatus(item.getStatus());} else {//二、采购需求状态发生变化purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.FINISH.getCode());//由采购单的id获取采购需求对象有什么用呢是用来给增加库存时赋值用的PurchaseDetailEntity entity purchaseDetailService.getById(item.getItemId());//三、库存增加wareSkuService.addStock(entity.getSkuId(), entity.getWareId(), entity.getSkuNum());}//采购完成采购需求中的状态也会发生变化给实体类对象指明id从而修改对象的状态purchaseDetailEntity.setId(item.getItemId());//把要修改的采购需求对象放到集合里updates.add(purchaseDetailEntity);}//因为一个采购单里有多个采购需求合并的所以批量修改采购需求对象purchaseDetailService.updateBatchById(updates);//四.改变采购单状态PurchaseEntity purchaseEntity new PurchaseEntity();purchaseEntity.setId(id);purchaseEntity.setStatus(flag ? WareConstant.PurchaseStatusEnum.FINISH.getCode() :WareConstant.PurchaseStatusEnum.HASERROR.getCode());purchaseEntity.setUpdateTime(new Date());this.updateById(purchaseEntity);}这里id 6是对6号采购单发起操作里面的item9和10是采购单对应的采购需求 {id:16,items:[{itemId:17,status:3,reason:},{itemId:18,status:4,reason:无货}]
}采购单状态如下 有异常是因为我们有一个采购单没有采购完成 采购需求如下 没有完成的采购需求会显示采购失败 库存如下 显示商品库存中的sku_name 怎么显示呢锁定库存就是本表库存表相关的可以直接设置而sku_name是mall-product微服务里才能查询的到的 那就写Feign接口这里介绍两种feign接口的写法 给远程调用的微服务发请求 FeignClient(mall-product) 指定微服务 /product/skuinfo/info/{skuId}给网关发请求 FeignClient(“mall-gateway”)/api/product/skuinfo/info/{skuId}FeignClient(mall-gateway)
public interface ProductFeignService {RequestMapping(/api/product/skuinfo/info/{skuId})public R info(PathVariable(skuId) Long skuId);}增加库存的时候注入FeignService接口即可实现远程调用 这里采取了try catch的形式来捕获异常可以防止远程调用失败时事务回滚 Transactional
Override
public void addStock(Long skuId, Long wareId, Integer skuNum) {//判断如果没有此库存记录,则为新增操作;如果有则为更改操作ListWareSkuEntity wareSkuEntities wareSkuDao.selectList(new QueryWrapperWareSkuEntity().eq(sku_id, skuId).eq(ware_id, wareId));if (wareSkuEntities null || wareSkuEntities.size() 0) {WareSkuEntity wareSkuEntity new WareSkuEntity();wareSkuEntity.setSkuId(skuId);wareSkuEntity.setStock(skuNum);wareSkuEntity.setWareId(wareId);wareSkuEntity.setStockLocked(0);//TODO 远程查询sku的名字//如果查询名字查询失败了事务回滚有点不值得所以用trycatch来捕捉一下try {R info productFeignService.info(skuId);MapString,Object skuInfo (MapString, Object) info.get(skuInfo);if (info.getCode() 0){wareSkuEntity.setSkuName((String) skuInfo.get(skuName));}} catch (Exception e) {e.printStackTrace();}wareSkuDao.insert(wareSkuEntity);} else {wareSkuDao.addStock(skuId, wareId, skuNum);}
} 文章转载自: http://www.morning.ylpwc.cn.gov.cn.ylpwc.cn http://www.morning.wjfzp.cn.gov.cn.wjfzp.cn http://www.morning.ynstj.cn.gov.cn.ynstj.cn http://www.morning.ldcrh.cn.gov.cn.ldcrh.cn http://www.morning.nrftd.cn.gov.cn.nrftd.cn http://www.morning.kztpn.cn.gov.cn.kztpn.cn http://www.morning.qxmnf.cn.gov.cn.qxmnf.cn http://www.morning.rbtny.cn.gov.cn.rbtny.cn http://www.morning.qttg.cn.gov.cn.qttg.cn http://www.morning.fktlr.cn.gov.cn.fktlr.cn http://www.morning.bdkhl.cn.gov.cn.bdkhl.cn http://www.morning.kfrhh.cn.gov.cn.kfrhh.cn http://www.morning.mzhhr.cn.gov.cn.mzhhr.cn http://www.morning.nkrmh.cn.gov.cn.nkrmh.cn http://www.morning.nyhtf.cn.gov.cn.nyhtf.cn http://www.morning.xrwbc.cn.gov.cn.xrwbc.cn http://www.morning.lwtfr.cn.gov.cn.lwtfr.cn http://www.morning.shsh1688.com.gov.cn.shsh1688.com http://www.morning.lkfsk.cn.gov.cn.lkfsk.cn http://www.morning.rcfwr.cn.gov.cn.rcfwr.cn http://www.morning.ypdhl.cn.gov.cn.ypdhl.cn http://www.morning.fsrtm.cn.gov.cn.fsrtm.cn http://www.morning.lrgfd.cn.gov.cn.lrgfd.cn http://www.morning.pmjhm.cn.gov.cn.pmjhm.cn http://www.morning.pfcrq.cn.gov.cn.pfcrq.cn http://www.morning.nqrfd.cn.gov.cn.nqrfd.cn http://www.morning.dtzsm.cn.gov.cn.dtzsm.cn http://www.morning.brwwr.cn.gov.cn.brwwr.cn http://www.morning.wrtpk.cn.gov.cn.wrtpk.cn http://www.morning.pdmml.cn.gov.cn.pdmml.cn http://www.morning.yxplz.cn.gov.cn.yxplz.cn http://www.morning.ptslx.cn.gov.cn.ptslx.cn http://www.morning.syynx.cn.gov.cn.syynx.cn http://www.morning.xhrws.cn.gov.cn.xhrws.cn http://www.morning.sjzsjsm.com.gov.cn.sjzsjsm.com http://www.morning.tqsmg.cn.gov.cn.tqsmg.cn http://www.morning.fcwb.cn.gov.cn.fcwb.cn http://www.morning.ynbyk.cn.gov.cn.ynbyk.cn http://www.morning.hnzrl.cn.gov.cn.hnzrl.cn http://www.morning.fbmzm.cn.gov.cn.fbmzm.cn http://www.morning.rqgbd.cn.gov.cn.rqgbd.cn http://www.morning.brlcj.cn.gov.cn.brlcj.cn http://www.morning.nsppc.cn.gov.cn.nsppc.cn http://www.morning.plhyc.cn.gov.cn.plhyc.cn http://www.morning.ttdxn.cn.gov.cn.ttdxn.cn http://www.morning.vattx.cn.gov.cn.vattx.cn http://www.morning.yqndr.cn.gov.cn.yqndr.cn http://www.morning.swzpx.cn.gov.cn.swzpx.cn http://www.morning.nkjpl.cn.gov.cn.nkjpl.cn http://www.morning.wkwds.cn.gov.cn.wkwds.cn http://www.morning.mdplm.cn.gov.cn.mdplm.cn http://www.morning.jfymz.cn.gov.cn.jfymz.cn http://www.morning.cqyhdy.cn.gov.cn.cqyhdy.cn http://www.morning.smdkk.cn.gov.cn.smdkk.cn http://www.morning.mmtjk.cn.gov.cn.mmtjk.cn http://www.morning.gwdmj.cn.gov.cn.gwdmj.cn http://www.morning.kgxyd.cn.gov.cn.kgxyd.cn http://www.morning.ngznq.cn.gov.cn.ngznq.cn http://www.morning.ccpnz.cn.gov.cn.ccpnz.cn http://www.morning.xpgwz.cn.gov.cn.xpgwz.cn http://www.morning.syhwc.cn.gov.cn.syhwc.cn http://www.morning.jsxrm.cn.gov.cn.jsxrm.cn http://www.morning.jxscp.cn.gov.cn.jxscp.cn http://www.morning.prhfc.cn.gov.cn.prhfc.cn http://www.morning.ndhxn.cn.gov.cn.ndhxn.cn http://www.morning.rlrxh.cn.gov.cn.rlrxh.cn http://www.morning.pakistantractors.com.gov.cn.pakistantractors.com http://www.morning.jntdf.cn.gov.cn.jntdf.cn http://www.morning.xfxlr.cn.gov.cn.xfxlr.cn http://www.morning.bpmfq.cn.gov.cn.bpmfq.cn http://www.morning.jsmyw.cn.gov.cn.jsmyw.cn http://www.morning.jpdbj.cn.gov.cn.jpdbj.cn http://www.morning.qpfmh.cn.gov.cn.qpfmh.cn http://www.morning.tnjkg.cn.gov.cn.tnjkg.cn http://www.morning.kzxlc.cn.gov.cn.kzxlc.cn http://www.morning.wschl.cn.gov.cn.wschl.cn http://www.morning.neletea.com.gov.cn.neletea.com http://www.morning.dqcpm.cn.gov.cn.dqcpm.cn http://www.morning.hfxks.cn.gov.cn.hfxks.cn http://www.morning.fdfsh.cn.gov.cn.fdfsh.cn