商品详情
详情数据的实体类
最外层
@Data
public class SkuItemVO {
/**
* 1、sku基本信息【标题、副标题、价格】pms_sku_info
* 2、sku图片信息【每个sku_id对应了多个图片】pms_sku_images
* 3、spu下所有sku销售属性组合【不只是当前sku_id所指定的商品】
* 4、spu商品介绍【】
* 5、spu规格与包装【参数信息】
*/
//1、sku基本信息(pms_sku_info)【默认图片、标题、副标题、价格】
private SkuInfoEntity info;
private boolean hasStock = true;// 是否有货
//2、sku图片信息(pms_sku_images)
private List<SkuImagesEntity> images;
//3、当前sku所属spu下的所有销售属性组合(pms_sku_sale_attr_value)
private List<SkuItemSaleAttrVO> saleAttr;
//4、spu商品介绍(pms_spu_info_desc)【描述图片】
private SpuInfoDescEntity desc;
//5、spu规格参数信息(pms_attr)【以组为单位】
private List<SpuItemAttrGroupVO> groupAttrs;
}
销售属性组合
@Data
@ToString
public class SkuItemSaleAttrVO {
/**
* 1.销售属性对应1个attrName
* 2.销售属性对应n个attrValue
* 3.n个sku包含当前销售属性(所以前端根据skuId交集区分销售属性的组合【笛卡尔积】)
*/
private Long attrId;
private String attrName;
private List<AttrValueWithSkuIdVO> attrValues;
}
@Data
public class AttrValueWithSkuIdVO {
private String attrValue;
private String skuIds;
}
规格参数
@Data
@ToString
public class SpuItemAttrGroupVO {
private String groupName;
private List<Attr> attrs;
}
@Data
public class Attr {
private Long attrId;
private String attrName;
private String attrValue;
private Integer searchType;
private Integer valueType;
private String icon;
private String valueSelect;
private Integer attrType;
private Long enable;
private Long catelogId;
private Integer showDesc;
}
Controller
@Controller
public class ItemController {
@Autowired
private SkuItemService skuItemService;
@GetMapping("/{skuId}.html")
public String item(@PathVariable("skuId") String skuId, Model model) throws ExecutionException, InterruptedException {
SkuItemVo skuItemVo = skuItemService.item(skuId);
model.addAttribute("item", skuItemVo);
return "item";
}
}
service查询VO返回(异步编排)
注意:
此处用到的重要技术就是异步编排的使用,开多个线程来查询不同数据的信息。并在主线程获取其返回结果。
@Service
public class SkuItemServiceImpl implements SkuItemService {
@Autowired
private SkuInfoService skuInfoService;
@Autowired
private SkuImagesService skuImagesService;
@Autowired
private SpuInfoDescService spuInfoDescService;
@Autowired
private AttrGroupService attrGroupService;
@Autowired
private SkuSaleAttrValueService skuSaleAttrValueService;
@Autowired
private ThreadPoolExecutor executor;
@Override
public SkuItemVo item(String skuId) throws ExecutionException, InterruptedException {
SkuItemVo skuItemVo = new SkuItemVo();
CompletableFuture<SkuInfoEntity> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
// 1.获取sku基本信息(pms_sku_info)【默认图片、标题、副标题、价格】
SkuInfoEntity skuInfoEntity = skuInfoService.getById(skuId);
skuItemVo.setInfo(skuInfoEntity);
return skuInfoEntity;
}, executor);
// 2.获取sku图片信息(pms_sku_images)
List<SkuImagesEntity> imagesEntityList = skuImagesService.getImgBySkuId(skuId);
skuItemVo.setImages(imagesEntityList);
CompletableFuture<Void> AttrFuture = skuInfoFuture.thenAcceptAsync(res -> {
// 3.获取当前sku所属spu下的所有销售属性组合(pms_sku_info、pms_sku_sale_attr_value)
List<SkuItemSaleAttrVo> skuItemSaleAttrVoList = skuSaleAttrValueService.getSaleAttrsBySpuId(res.getSpuId());
skuItemVo.setSaleAttr(skuItemSaleAttrVoList);
}, executor);
CompletableFuture<Void> spuDescFuture = skuInfoFuture.thenAcceptAsync(res -> {
// 4.获取spu商品介绍(pms_spu_info_desc)【描述图片】
SpuInfoDescEntity spuInfoDescEntity = spuInfoDescService.getById(res.getSpuId());
skuItemVo.setDesc(spuInfoDescEntity);
}, executor);
CompletableFuture<Void> groupFuture = skuInfoFuture.thenAcceptAsync((res -> {
// 5.获取spu规格参数信息(pms_product_attr_value、pms_attr_attrgroup_relation、pms_attr_group)
List<SpuItemAttrGroupVo> groupAttrList = attrGroupService.getGroupAttrGroupWithAttrsBySpuId(res.getSpuId(), res.getCatalogId());
skuItemVo.setGroupAttrs(groupAttrList);
}), executor);
CompletableFuture.allOf(skuInfoFuture, AttrFuture, spuDescFuture, groupFuture).get(); // 阻塞等待所有执行完成
return skuItemVo;
}
}
获取spu销售属性组合(笛卡尔积)
查询所有属性的skuId交集,组成sku笛卡尔积
GROUP_CONCAT操作是将所有分组的sku_id连接起来,注意去重
获取当前sku所属spu下的所有销售属性组合(pms_sku_info、pms_sku_sale_attr_value)
// 1.通过spuId查询所有sku(pms_sku_info)
// 2.查询sku涉及到的所有销售属性(pms_sku_sale_attr_value)
/**
* 1.销售属性对应1个attrName
* 2.销售属性对应n个attrValue
* 3.n个sku包含当前销售属性(所以前端根据skuId交集区分销售属性的组合【笛卡尔积】)
* sku_ids用,切割成List<String> skuIds
*/
<resultMap id="skuItemSaleAttrVo" type="com.atguigu.gulimall.product.vo.SkuItemSaleAttrVo">
<result column="attr_id" property="attrId"></result>
<result column="attr_name" property="attrName"></result>
<collection property="attrValues" ofType="com.atguigu.gulimall.product.vo.AttrValueWithSkuIdVo">
<result column="attr_value" property="attrValue"></result>
<result column="sku_ids" property="skuIds"></result>
</collection>
</resultMap>
<select id="getSaleAttrsBySpuId" resultMap="skuItemSaleAttrVo">
SELECT pss.attr_id, pss.attr_name, pss.attr_value, GROUP_CONCAT(DISTINCT pss.sku_id) sku_ids
FROM pms_sku_info ps
LEFT JOIN pms_sku_sale_attr_value pss ON pss.sku_id = ps.sku_id
WHERE ps.spu_id = #{spuId}
GROUP BY pss.attr_id, pss.attr_name, pss.attr_value;
</select>
获取spu规格参数信息
<resultMap id="spuItemAttrGroupVo" type="com.atguigu.gulimall.product.vo.SpuItemAttrGroupVo">
<result property="groupName" column="attr_group_name"></result>
<collection property="attrs" ofType="com.atguigu.gulimall.product.vo.Attr">
<result property="attrId" column="attr_id"></result>
<result property="attrName" column="attr_name"></result>
<result property="attrValue" column="attr_value"></result>
</collection>
</resultMap>
<!-- 自定义返回结果集 -->
<select id="getGroupAttrGroupWithAttrsBySpuId" resultMap="spuItemAttrGroupVo">
SELECT pav.spu_id, ag.attr_group_name, ag.attr_group_id, pa.attr_id, pa.attr_name, pav.attr_value
FROM pms_attr_group ag
LEFT JOIN pms_attr_attrgroup_relation paa ON paa.attr_group_id = ag.attr_group_id
LEFT JOIN pms_attr pa ON pa.attr_id = paa.attr_id
LEFT JOIN pms_product_attr_value pav ON pav.attr_id = pa.attr_id
WHERE ag.catelog_id = #{catalogId}
AND pav.spu_id = #{spuId};
</select>