Description or Example
# BUG修复
## 1. 组函数出现的错误
> 主要是实体类写错了类型
## 2.第一种找不到符号

> 原因是项目没有打包或下载到本地库, 因此会出现找不到符号的情况
## 3. 第二种找不到符号的情况
> 一般来说是打包的时候找不到符号, 这种一般是被依赖的东西被又被打包, 所以找不到符号, 把被依赖的模块打包即可
## 4. 第三种找不到符号的情况
> 这种是最莫名其妙的情况, 一般无法溯源, 若出现该状况, 做出如下操作


## 5. BasSQL的解决
> 我这里的原因是, WHERE写在了GROUPBY后, 因此, 注意SQL的声明顺序
# 要点
## 如果实体类涉及到xml, 不能用内部类
> 因为mybaits的xml无法解析内部类
# 配置步骤
1. 配置子域名
2. 配置NGINX和网关
3. 转储视图和静态资源
# 核心代码
```java
@GetMapping("/{skuId}.html")
public ModelAndView toItem(ModelAndView mv, @PathVariable String skuId) {
ProductItemVO productItemVO = skuInfoService.getProductItemBySkuId(skuId);
mv.setViewName("item");
mv.addObject("item", productItemVO);
return mv;
}
```
非异步版
```java
@Override
public ProductItemVO getProductItemBySkuId(String skuId) {
// 1. 获取sku的基本信息
SkuInfoEntity info = this.getById(skuId);
// 获取spuId 和 分类id
Long spuId = info.getSpuId();
Long catalogId = info.getCatalogId();
// 2. 获取sku的图片集
LambdaQueryWrapper<SkuImagesEntity> skuImagesEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
skuImagesEntityLambdaQueryWrapper.eq(SkuImagesEntity::getSkuId, skuId);
List<SkuImagesEntity> images = skuImagesService.getBaseMapper().selectList(skuImagesEntityLambdaQueryWrapper);
//3. 获取SPU的描述图片
SpuInfoDescEntity desc = spuInfoDescService.getById(spuId);
//4. 获取规格参数信息
List<ItemAttrGroupVO> attrGroups = attrGroupService.getItemAttrGroups(spuId, catalogId);
//5. 获取销售属性
List<ItemSaleAttrVO> saleAttrs = skuSaleAttrValueService.getAllSkuItem(spuId);
return new ProductItemVO()
.setInfo(info)
.setImages(images)
.setAttrGroups(attrGroups)
.setSpuDesc(desc)
.setSaleAttrs(saleAttrs);
}
```
```xml
<select id="getAllSkuItem" resultMap="ItemSaleAttrVO">
SELECT pssav.attr_name, pssav.attr_value, GROUP_CONCAT(DISTINCT psi.sku_id) AS skus
FROM pms_sku_info psi
JOIN bitmall_pms.pms_sku_sale_attr_value pssav on psi.sku_id = pssav.sku_id
WHERE psi.spu_id = #{spuId}
GROUP BY pssav.attr_name, pssav.attr_value
</select>
```
### 思想1
1. 首先通过SPU找到这个SPU下所有的SKU
2. 然后通过SKU的ID找到对应对应SKU的详细信息, 如name和value
3. 通过组函数统计该值出现的SKUID
```xml
<select id="getItemAttrGroups" resultMap="ItemAttrGroupVO">
SELECT ag.attr_group_name, ar.attr_name, pav.attr_value
FROM pms_attr_group ag
JOIN pms_attr_attrgroup_relation re ON ag.attr_group_id = re.attr_group_id
JOIN pms_attr ar ON ar.attr_id = re.attr_id
JOIN pms_product_attr_value pav ON pav.attr_id = ar.attr_id
WHERE ag.catelog_id = #{catalogId} AND pav.spu_id = #{spuId}
</select>
```
### 思想2
1. 通过分类id过滤出当前分类下所有的属性分组, 并获取对应的名字
2. 通过属性分组和属性的关联关系表, 找到属性id, 然后通过属性表, 找出属性的详细信息
3. 最后通过属性id, 在属性值表找出对应的值
## 异步编排代码
```java
@Override
public ProductItemVO getProductItemBySkuId(String skuId) {
ProductItemVO productItemVO = new ProductItemVO();
CompletableFuture<SkuInfoEntity> stage1A = CompletableFuture.supplyAsync(() -> {
// 1. 获取sku的基本信息
// 返回info, 然后其他阶段获取spuId 和 分类id
SkuInfoEntity info = this.getById(skuId);
productItemVO.setInfo(info);
return info;
}, threadPool);
CompletableFuture<Void> stage2A = stage1A.thenAcceptAsync(info -> {
//3. 获取SPU的描述图片
SpuInfoDescEntity desc = spuInfoDescService.getById(info.getSpuId());
productItemVO.setSpuDesc(desc);
}, threadPool);
CompletableFuture<Void> stage2B = stage1A.thenAcceptAsync(info -> {
//4. 获取规格参数信息
List<ItemAttrGroupVO> attrGroups = attrGroupService.getItemAttrGroups(info.getSpuId(), info.getCatalogId());
productItemVO.setAttrGroups(attrGroups);
}, threadPool);
CompletableFuture<Void> stage2C = stage1A.thenAcceptAsync(info -> {
//5. 获取销售属性
List<ItemSaleAttrVO> saleAttrs = skuSaleAttrValueService.getAllSkuItem(info.getSpuId());
productItemVO.setSaleAttrs(saleAttrs);
}, threadPool);
CompletableFuture<Void> stage1B = CompletableFuture.runAsync(() -> {
// 2. 获取sku的图片集
LambdaQueryWrapper<SkuImagesEntity> skuImagesEntityLambdaQueryWrapper;
skuImagesEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
skuImagesEntityLambdaQueryWrapper.eq(SkuImagesEntity::getSkuId, skuId);
List<SkuImagesEntity> images = skuImagesService.getBaseMapper().selectList(skuImagesEntityLambdaQueryWrapper);
productItemVO.setImages(images);
}, threadPool);
CompletableFuture<Void> stage1C = CompletableFuture.runAsync(() -> {
R info = secKillService.getSkuSeckillInfo(skuId);
if (info.getCode() == 0) {
SeckillSkuTO seckillSkuTO = info.getData(new TypeReference<SeckillSkuTO>() {});
productItemVO.setSeckillSkuTO(seckillSkuTO); // 设置秒杀商品相关的信息
}
}, threadPool);
// 等待所有任务的完成
CompletableFuture.allOf(stage1B, stage2A, stage2B, stage2C, stage1C).join();
}
```
[架构图](https://www.processon.com/embed/64dafbdca5b02a67a257273e)