package com.iotechn.unimall.biz.service.product; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dobbinsoft.fw.core.exception.BizServiceException; import com.dobbinsoft.fw.core.exception.CoreExceptionDefinition; import com.dobbinsoft.fw.core.exception.ServiceException; import com.dobbinsoft.fw.support.component.CacheComponent; import com.dobbinsoft.fw.support.model.Page; import com.iotechn.unimall.biz.service.category.CategoryBizService; import com.iotechn.unimall.data.constant.CacheConst; import com.iotechn.unimall.data.domain.*; import com.iotechn.unimall.data.dto.product.AdminSpuDTO; import com.iotechn.unimall.data.dto.product.SkuDTO; import com.iotechn.unimall.data.dto.product.SpuDTO; import com.iotechn.unimall.data.enums.BizType; import com.iotechn.unimall.data.enums.StatusType; import com.iotechn.unimall.data.exception.ExceptionDefinition; import com.iotechn.unimall.data.mapper.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.DefaultTypedTuple; import org.springframework.data.redis.core.ZSetOperations; import org.springframework.stereotype.Service; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.transaction.support.TransactionTemplate; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; /** * Created by rize on 2019/7/12. */ @Service public class ProductBizService { @Autowired private SpuMapper spuMapper; @Autowired private SkuMapper skuMapper; @Autowired private SpuAttributeMapper spuAttributeMapper; @Autowired private ImgMapper imgMapper; @Autowired private SpuSpecificationMapper spuSpecificationMapper; @Autowired private CategoryBizService categoryBizService; @Autowired private CacheComponent cacheComponent; // @Autowired(required = false) // private SearchEngine searchEngine; /** * SPU 排除掉detail字段的其他字段名字形成的数组 */ public static final String[] SPU_EXCLUDE_DETAIL_FIELDS; private static final Logger logger = LoggerFactory.getLogger(ProductBizService.class); static { Field[] fields = SpuDO.class.getDeclaredFields(); List tempList = new ArrayList<>(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; String name = StrUtil.toUnderlineCase(field.getName()); if (!name.equals("detail")) { tempList.add(name); } } tempList.add("id"); tempList.add("gmt_update"); tempList.add("gmt_create"); SPU_EXCLUDE_DETAIL_FIELDS = tempList.toArray(new String[0]); } /** * 创建商品 抽取方法 * @param adminSpuDTO * @return * @throws ServiceException */ public String create(AdminSpuDTO adminSpuDTO) throws ServiceException { // 1.参数校验 if (adminSpuDTO.getId() != null) { throw new BizServiceException(ExceptionDefinition.PRODUCT_CREATE_HAS_ID); } if (CollectionUtils.isEmpty(adminSpuDTO.getSkuList())) { throw new BizServiceException(ExceptionDefinition.PRODUCT_SKU_LIST_EMPTY); } // 1.2.校验Sku是否重复 Set barCodes = adminSpuDTO.getSkuList().stream().map(item -> item.getBarCode()).collect(Collectors.toSet()); if (barCodes.size() != adminSpuDTO.getSkuList().size()) { throw new BizServiceException(ExceptionDefinition.PRODUCT_UPLOAD_SKU_BARCODE_REPEAT); } List existSkuDO = skuMapper.selectList(new QueryWrapper().in("bar_code", barCodes)); if (!CollectionUtils.isEmpty(existSkuDO)) { String spuIds = existSkuDO.stream().map(item -> item.getSpuId().toString()).collect(Collectors.joining(",")); String skuIds = existSkuDO.stream().map(item -> item.getBarCode()).collect(Collectors.joining(",")); throw new BizServiceException(CoreExceptionDefinition .buildVariableException(ExceptionDefinition.PRODUCT_CREATE_BARCODE_REPEAT, spuIds, skuIds)); } // 2.1.插入主表 Date now = new Date(); SpuDO spuDO = new SpuDO(); BeanUtils.copyProperties(adminSpuDTO, spuDO); spuDO.setGmtUpdate(now); spuDO.setGmtCreate(now); spuDO.setSales(0); packPrice(adminSpuDTO, spuDO); spuMapper.insert(spuDO); adminSpuDTO.setId(spuDO.getId()); // 2.2.插入SKU表 for (SkuDO skuDO : adminSpuDTO.getSkuList()) { skuDO.setSpuId(spuDO.getId()); skuDO.setGmtUpdate(now); skuDO.setGmtCreate(now); skuMapper.insert(skuDO); } // 2.3.插入spuAttr insertSpuAttribute(adminSpuDTO, now); // 2.4.插入IMG insertSpuImg(adminSpuDTO, spuDO.getId(), now); // 2.5.插入规格维度 List specificationList = adminSpuDTO.getSpecificationList(); specificationList.forEach(item -> { // 为SpuSpecificationDO 赋值上默认值 item.setSpuId(spuDO.getId()); item.setId(null); item.setGmtCreate(now); item.setGmtUpdate(now); }); spuSpecificationMapper.insertBatchSomeColumn(specificationList); // 3.1. 创建商品缓存 this.createSpuCache(spuDO); // 3.2. 创建Sku库存缓存 for (SkuDO skuDO : adminSpuDTO.getSkuList()) { cacheComponent.putHashRaw(CacheConst.PRT_SKU_STOCK_BUCKET, "K" + skuDO.getId(), skuDO.getStock() + ""); } // 4. TODO 同步到搜索引擎 // if (searchEngine != null) { // TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { // @Override // public void afterCommit() { // AdminProductServiceImpl.this.transmissionSearchEngine(spuDO.getId()); // } // }); // // } return "ok"; } /** * 封装商品原价/VIP价等 * @param adminSpuDTO * @param spuDO * @throws BizServiceException */ private void packPrice(AdminSpuDTO adminSpuDTO, SpuDO spuDO) throws BizServiceException { SkuDO minPriceSku = null; for (SkuDO skuDO : adminSpuDTO.getSkuList()) { if (skuDO.getOriginalPrice() < skuDO.getPrice() || skuDO.getPrice() < skuDO.getVipPrice() || skuDO.getOriginalPrice() < skuDO.getVipPrice()) { throw new BizServiceException(ExceptionDefinition.PRODUCT_PRICE_CHECKED_FAILED); } if (minPriceSku == null) { minPriceSku = skuDO; } if (minPriceSku.getPrice() > skuDO.getPrice()) { minPriceSku = skuDO; } } spuDO.setOriginalPrice(minPriceSku.getOriginalPrice()); spuDO.setPrice(minPriceSku.getPrice()); spuDO.setVipPrice(minPriceSku.getVipPrice()); } /** * 编辑商品 抽取方法 * @param spuDTO * @return * @throws ServiceException */ public String edit(AdminSpuDTO spuDTO) throws ServiceException { // 1. 参数校验 if (spuDTO.getId() == null) { throw new BizServiceException(ExceptionDefinition.PARAM_CHECK_FAILED); } if (CollectionUtils.isEmpty(spuDTO.getSkuList())) { throw new BizServiceException(ExceptionDefinition.PRODUCT_SKU_LIST_EMPTY); } // 将旧值查询出来,若价格没有改变,则无需更新价格排序缓存 SpuDO spuFromDB = spuMapper.selectById(spuDTO.getId()); // 2.1. 更新主表 Date now = new Date(); SpuDO spuDO = new SpuDO(); BeanUtils.copyProperties(spuDTO, spuDO); packPrice(spuDTO, spuDO); spuMapper.updateById(spuDO); // 2.2. 更新barCodes Set barCodes = new HashSet<>(); for (SkuDO skuDO : spuDTO.getSkuList()) { if (skuDO.getOriginalPrice() < skuDO.getPrice() || skuDO.getPrice() < skuDO.getVipPrice() || skuDO.getOriginalPrice() < skuDO.getVipPrice()) { throw new BizServiceException(ExceptionDefinition.PRODUCT_PRICE_CHECKED_FAILED); } skuDO.setId(null); skuDO.setSpuId(spuDO.getId()); skuDO.setGmtUpdate(now); if (skuMapper.update(skuDO, new QueryWrapper() .eq("bar_code", skuDO.getBarCode())) <= 0) { skuDO.setGmtCreate(now); skuMapper.insert(skuDO); } boolean succ = barCodes.add(skuDO.getBarCode()); if (!succ) { throw new BizServiceException(ExceptionDefinition.PRODUCT_UPLOAD_SKU_BARCODE_REPEAT); } } // 2.2.2. 删除多余barCode skuMapper.delete(new QueryWrapper().eq("spu_id", spuDO.getId()).notIn("bar_code", barCodes)); // 2.3. 更新spuAttr spuAttributeMapper.delete(new QueryWrapper().eq("spu_id", spuDTO.getId())); insertSpuAttribute(spuDTO, now); imgMapper.delete(new QueryWrapper().eq("biz_id", spuDO.getId()).eq("biz_type", BizType.GOODS.getCode())); // 2.4. 插入IMG insertSpuImg(spuDTO, spuDO.getId(), now); // TODO 2.5. 更新规格维度 // 3. 删除缓存 // 对于更新缓存,需要在事务提交后更新,防止事务提交期间产生读请求,将旧值覆盖到新值上 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { // 3.1. 检测商品价格、类目是否发生了改变,根据情况更新缓存 if (spuFromDB.getCategoryId().longValue() != spuDO.getCategoryId().longValue()) { // 3.1.1. 若二者CategoryId不一致,则表示商品更改了类目 更新列表排序缓存 // 3.1.1.1 删除旧列表中的值 List oldCategoryFamily = categoryBizService.getCategoryFamily(spuFromDB.getCategoryId()); for (Long oldCid : oldCategoryFamily) { cacheComponent.delZSet(CacheConst.PRT_CATEGORY_ORDER_ID_ZSET + oldCid, "P" + spuDO.getId()); cacheComponent.delZSet(CacheConst.PRT_CATEGORY_ORDER_PRICE_ZSET + oldCid, "P" + spuDO.getId()); cacheComponent.delZSet(CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + oldCid, "P" + spuDO.getId()); } // 3.1.1.2 添加新列表中的值 if (spuDO.getStatus().intValue() == StatusType.ACTIVE.getCode()) { List newCategoryFamily = categoryBizService.getCategoryFamily(spuDO.getCategoryId()); for (Long newCid : newCategoryFamily) { cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_ID_ZSET + newCid, spuDO.getId(), "P" + spuDO.getId()); cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_PRICE_ZSET + newCid, spuDO.getPrice(), "P" + spuDO.getId()); cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + newCid, spuFromDB.getSales(), "P" + spuDO.getId()); } } } List categoryFamily = categoryBizService.getCategoryFamily(spuDO.getCategoryId()); if (spuFromDB.getPrice().intValue() != spuDO.getPrice().intValue()) { // 3.1.2.若二者Price不一致,则表示商品更新了价格 更新列表缓存 if (spuDO.getStatus().intValue() == StatusType.ACTIVE.getCode()) { for (Long categoryId : categoryFamily) { cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_PRICE_ZSET + categoryId, spuDO.getPrice(), "P" + spuDO.getId()); } } } // 3.2. 更新基本信息缓存 SpuDTO basicSpuDTO = new SpuDTO(); BeanUtils.copyProperties(spuDO, basicSpuDTO, "detail"); basicSpuDTO.setCategoryIds(categoryFamily); cacheComponent.putHashObj(CacheConst.PRT_SPU_HASH_BUCKET, "P" + spuDO.getId(), basicSpuDTO); // 3.3. 删除详细信息缓存 cacheComponent.delHashKey(CacheConst.PRT_SPU_DETAIL_HASH_BUCKET, "P" + spuDO.getId()); // 3.4. 更新Sku库存缓存 for (SkuDO skuDO : spuDTO.getSkuList()) { cacheComponent.putHashRaw(CacheConst.PRT_SKU_STOCK_BUCKET, "K" + skuDO.getId(), skuDO.getStock() + ""); } // 4 更新搜索引擎 ProductBizService.this.transmissionSearchEngine(spuDO.getId()); } }); return "ok"; } private void insertSpuAttribute(AdminSpuDTO spuDTO, Date now) { if (!CollectionUtils.isEmpty(spuDTO.getAttributeList())) { for (SpuAttributeDO spuAttributeDO : spuDTO.getAttributeList()) { spuAttributeDO.setSpuId(spuDTO.getId()); spuAttributeDO.setGmtUpdate(now); spuAttributeDO.setGmtCreate(now); spuAttributeMapper.insert(spuAttributeDO); } } } private void insertSpuImg(AdminSpuDTO spuDTO, Long bizId, Date now) { List imgList = spuDTO.getImgList(); List imgDOList = imgList.stream().map(item -> { ImgDO imgDO = new ImgDO(); imgDO.setBizType(BizType.GOODS.getCode()); imgDO.setBizId(bizId); imgDO.setUrl(item); imgDO.setGmtCreate(now); imgDO.setGmtUpdate(now); return imgDO; }).collect(Collectors.toList()); imgMapper.insertBatchSomeColumn(imgDOList); } public void transmissionSearchEngine(Long id) { // TODO // if (searchEngine != null) { // GlobalExecutor.execute(() -> { // SpuDO spuFromDB = AdminProductServiceImpl.this.productBizService.getProductByIdFromDB(id); // searchEngine.dataTransmission(spuFromDB); // }); // } } public void deleteSearchEngine(Long id) { // TODO // if (searchEngine != null) { // GlobalExecutor.execute(() -> { // SpuDO spuDO = new SpuDO(); // spuDO.setId(id); // searchEngine.deleteData(spuDO); // }); // } } /** * 若搜索关键字为空,则从缓存中获取商品列表,此列表不包含detail(商品详情)字段 * * @param pageNo * @param pageSize * @param categoryId * @param orderBy * @param isAsc * @param title * @return * @throws ServiceException */ public Page getProductPage(Integer pageNo, Integer pageSize, Long categoryId, String orderBy, Boolean isAsc, String title) throws ServiceException { if (!StringUtils.isEmpty(title)) { // TODO 搜索引擎 // try { // if (this.searchEngine != null) { // SearchWrapperModel searchWrapper = // new SearchWrapperModel() // .div(pageNo, pageSize) // .like("title", title); // if (categoryId != null && categoryId > 0) { // searchWrapper.eq("category_id", categoryId); // } // if (orderBy != null && isAsc != null) { // if (isAsc) // searchWrapper.orderByAsc(orderBy); // else // searchWrapper.orderByDesc(orderBy); // } // Page searchRes = searchEngine.search(searchWrapper, SpuDO.class); // return searchRes; // } // } catch (SearchEngineException e) { // logger.error("[获取商品列表] 搜素引擎 异常", e); // throw new AppServiceException(ExceptionDefinition.buildVariableException(ExceptionDefinition.SEARCH_ENGINE_INNER_EXCEPTION, e.getMessage())); // } // 使用DB逻辑 return this.getProductPageFromDB(pageNo, pageSize, categoryId, orderBy, isAsc, title); } // 1. 从商品列表缓存中取出Id String zsetBucketKey; if ("price".equals(orderBy)) { zsetBucketKey = CacheConst.PRT_CATEGORY_ORDER_PRICE_ZSET + categoryId; } else if ("id".equals(orderBy)) { zsetBucketKey = CacheConst.PRT_CATEGORY_ORDER_ID_ZSET + categoryId; } else if ("sales".equals(orderBy)) { zsetBucketKey = CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + categoryId; } else { throw new BizServiceException(ExceptionDefinition.GOODS_ORDER_BY_WAY_ILLEGAL); } Page page = cacheComponent.getZSetPage(zsetBucketKey, pageNo, pageSize, isAsc); if (page.getTotal() == 0) { // 若没有缓存,则尝试从DB读取 List productIdsFromDB = getProductIdsOnSaleFromDB(categoryId); // 传入一个categoryId,将所有该Category(包括子节点) 的全部商品Id和销量查询出来。若传入的CategoryId为null,则查出所有的商品 if (!CollectionUtils.isEmpty(productIdsFromDB)) { // 若非空,则全部放入ZSet中 Set> set = productIdsFromDB.stream().map(item -> (ZSetOperations.TypedTuple) (new DefaultTypedTuple("P" + item.getId(), item.getSales().doubleValue()))).collect(Collectors.toSet()); // 放入缓存 cacheComponent.putZSetMulti(zsetBucketKey, set); // 重新从缓存中读取 page = cacheComponent.getZSetPage(zsetBucketKey, pageNo, pageSize, isAsc); } } // 从Spu Hash桶里面取数据。获取到这页Id所对应的Spu List spuList = cacheComponent.getHashMultiAsList(CacheConst.PRT_SPU_HASH_BUCKET, page.getItems(), SpuDO.class); boolean hasEmptyObj = false; for (int i = 0; i < spuList.size(); i++) { SpuDO spuDO = spuList.get(i); if (spuDO == null) { // 去数据库获取 SpuDO spuDOFromDB = spuMapper.selectOne(new QueryWrapper().select(SPU_EXCLUDE_DETAIL_FIELDS).eq("id", Long.parseLong(page.getItems().get(i).replace("P", "")))); if (spuDOFromDB == null) { // 这种情况几乎不可能 hasEmptyObj = true; logger.error("[缓存数据库不一致] key=" + zsetBucketKey + ";item=" + page.getItems().get(i)); cacheComponent.delZSet(zsetBucketKey, page.getItems().get(i)); } else { // 更新 spuList 列表 spuList.set(i, spuDOFromDB); // 获取ClassifyIds List familyCategoryIds = categoryBizService.getCategoryFamily(spuDOFromDB.getCategoryId()); SpuDTO spuDTO = new SpuDTO(); BeanUtils.copyProperties(spuDOFromDB, spuDTO); spuDTO.setCategoryIds(familyCategoryIds); cacheComponent.putHashObj(CacheConst.PRT_SPU_HASH_BUCKET, "P" + spuDOFromDB.getId(), spuDTO); } } } if (hasEmptyObj) { spuList = spuList.stream().filter(item -> item != null).collect(Collectors.toList()); } return page.replace(spuList); } /** * 从数据库中获取商品,此列表不包含detail(商品详情)字段 * * @param pageNo * @param pageSize * @param categoryId * @param orderBy * @param isAsc * @param title * @return */ public Page getProductPageFromDB(Integer pageNo, Integer pageSize, Long categoryId, String orderBy, Boolean isAsc, String title) throws ServiceException { QueryWrapper wrapper = new QueryWrapper(); wrapper.select(SPU_EXCLUDE_DETAIL_FIELDS); if (orderBy != null && isAsc != null) { if (isAsc) { wrapper.orderByAsc(orderBy); } else { wrapper.orderByDesc(orderBy); } } if (categoryId != null) { wrapper.eq("category_id", categoryId); } if (!ObjectUtils.isEmpty(title)) { wrapper.like("title", title); } return spuMapper.selectPage(Page.div(pageNo, pageSize, SpuDO.class), wrapper); } /** * 从数据库中获取列表Id、销量 (在售) * * @param categoryId * @return */ private List getProductIdsOnSaleFromDB(Long categoryId) throws ServiceException { if (categoryId != null) { List categoryFamily = categoryBizService.getCategorySelfAndChildren(categoryId); return spuMapper.selectList(new QueryWrapper().select("id", "sales").eq("status", StatusType.ACTIVE.getCode()).in("category_id", categoryFamily)); } else { return spuMapper.selectList(new QueryWrapper().eq("status", StatusType.ACTIVE.getCode()).select("id", "sales")); } } /** * 从数据库中获取SKU详细信息 * * @param skuIds * @return */ public List getSkuListByIds(List skuIds) { return skuMapper.getSkuDTOListByIds(skuIds); } /** * 从数据库中获取SPU,并且不查出detail字段 * * @param id * @return */ public SpuDO getProductByIdFromDB(Long id) { return spuMapper.selectOne(new QueryWrapper().select(SPU_EXCLUDE_DETAIL_FIELDS).eq("id", id)); } public SpuDO getProductByIdFromDBForUpdate(Long id) { return spuMapper.selectOne(new QueryWrapper().select(SPU_EXCLUDE_DETAIL_FIELDS).eq("id", id).last(" FOR UPDATE")); } /** * TODO 从缓存中查出SPU,不带detail字段 * * @param spuId * @return */ public SpuDTO getProductByIdFromCache(Long spuId) throws ServiceException { SpuDTO spuDTO = null; // cacheComponent.getHashObj(CacheConst.PRT_SPU_HASH_BUCKET, "P" + spuId, SpuDTO.class); if (spuDTO == null) { SpuDO spuDO = spuMapper.selectOne(new QueryWrapper().select(ProductBizService.SPU_EXCLUDE_DETAIL_FIELDS).eq("id", spuId)); if (spuDO != null) { spuDTO = new SpuDTO(); BeanUtils.copyProperties(spuDO, spuDTO); List categoryFamily = categoryBizService.getCategoryFamily(spuDO.getCategoryId()); spuDTO.setCategoryIds(categoryFamily); // cacheComponent.putHashObj(CacheConst.PRT_SPU_HASH_BUCKET, "P" + spuId, spuDTO); } else { throw new BizServiceException(ExceptionDefinition.PRODUCT_NOT_EXIST); } } return spuDTO; } /** * 扣减库存 * * @param skuStockMap */ public void decSkuStock(Map skuStockMap) { skuStockMap.forEach((k, v) -> skuMapper.decSkuStock(k, v)); } @Autowired private TransactionTemplate transactionTemplate; /** * 增加商品销量 * * @param skuSalesMap */ public void incSpuSales(Map skuSalesMap) { skuSalesMap.forEach((k, v) -> { // 1. 更新数据库 spuMapper.incSales(k, v); // 2. 更新缓存 SpuDTO spuDtoFromCache = cacheComponent.getHashObj(CacheConst.PRT_SPU_HASH_BUCKET, "P" + k, SpuDTO.class); int isTheSame = -1; Double nullSource = cacheComponent.incZSetSource(CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + null, "P" + k, v); if (nullSource != null) { isTheSame = (int) Math.round(nullSource); } for (Long categoryId : spuDtoFromCache.getCategoryIds()) { Double source = cacheComponent.incZSetSource(CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + categoryId, "P" + k, v); if (source != null) { int i = (int) Math.round(source); if (i != isTheSame) { // 若不相等 isTheSame = - 1; } } } if (isTheSame == -1) { // 则重新冲数据库建立新的缓存 (一般情况下不会执行到这里) transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { // 锁定此ID的记录,防止脏读 SpuDO newSpuDO = ProductBizService.this.getProductByIdFromDBForUpdate(k); List categoryFamily = categoryBizService.getCategoryFamily(newSpuDO.getCategoryId()); SpuDTO newSpuDto = new SpuDTO(); BeanUtils.copyProperties(newSpuDO, newSpuDto); newSpuDto.setCategoryIds(categoryFamily); cacheComponent.putHashObj(CacheConst.PRT_SPU_HASH_BUCKET, "P" + k, newSpuDto); for (Long categoryId : categoryFamily) { cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + categoryId, newSpuDO.getSales(), "P" + newSpuDO.getId()); } cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + null, newSpuDO.getSales(), "P" + newSpuDO.getId()); } }); } else { spuDtoFromCache.setSales(isTheSame); cacheComponent.putHashObj(CacheConst.PRT_SPU_HASH_BUCKET, "P" + k, spuDtoFromCache); } // TODO 3. 更新搜索引擎 // final SpuDTO finalSpuDto = spuDtoFromCache; // GlobalExecutor.execute(() -> { // if (searchEngine != null) { // SpuDO newSpuDO = new SpuDO(); // BeanUtils.copyProperties(finalSpuDto, newSpuDO); // searchEngine.dataTransmission(newSpuDO); // } // }); }); } /** * 调整商品库存 * * @param barCode * @param stock */ @Transactional(rollbackFor = Exception.class, propagation = Propagation.MANDATORY) public boolean adjustSkuStock(String barCode, Integer stock) { SkuDO skuFromDB = skuMapper.selectOne(new QueryWrapper().select("id", "stock").eq("bar_code", barCode)); if (skuFromDB == null || skuFromDB.getStock().intValue() == stock.intValue()) { return false; } SkuDO skuDO = new SkuDO(); skuDO.setId(skuFromDB.getId()); skuDO.setStock(stock); TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { cacheComponent.putHashRaw(CacheConst.PRT_SKU_STOCK_BUCKET, "K" + skuDO.getId(), skuDO.getStock() + ""); } }); return skuMapper.updateById(skuDO) > 0; } /** * 1.放入各个类目ZSET * 2.放入基本信息Hash表 * 3.不放入详细信息Hash表,读取时再放入缓存 * * @param spuDO */ public void createSpuCache(SpuDO spuDO) { // 1. 放入类目缓存 List categoryFamily = categoryBizService.getCategoryFamily(spuDO.getCategoryId()); if (spuDO.getStatus().intValue() == StatusType.ACTIVE.getCode()) { for (Long categoryId : categoryFamily) { cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_ID_ZSET + categoryId, spuDO.getId(), "P" + spuDO.getId()); cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_PRICE_ZSET + categoryId, spuDO.getPrice(), "P" + spuDO.getId()); cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + categoryId, 0, "P" + spuDO.getId()); } cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_ID_ZSET + null, spuDO.getId(), "P" + spuDO.getId()); cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_PRICE_ZSET + null, spuDO.getPrice(), "P" + spuDO.getId()); cacheComponent.putZSet(CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + null, 0, "P" + spuDO.getId()); } // 2. 放入Hash表中 spuDO.setDetail(null); SpuDTO newSpuDTO = new SpuDTO(); BeanUtils.copyProperties(spuDO, newSpuDTO); newSpuDTO.setCategoryIds(categoryFamily); cacheComponent.putHashObj(CacheConst.PRT_SPU_HASH_BUCKET, "P" + spuDO.getId(), newSpuDTO); } /** * 1.删除各个类目ZSET * 2.删除基本信息Hash表 * 3.删除商品详情信息Hash表 * * @param spuDO */ public void deleteSpuCache(SpuDO spuDO) { // 1. 删除各个类目ZSET List categoryFamily = categoryBizService.getCategoryFamily(spuDO.getCategoryId()); for (Long categoryId : categoryFamily) { cacheComponent.delZSet(CacheConst.PRT_CATEGORY_ORDER_ID_ZSET + categoryId, "P" + spuDO.getId()); cacheComponent.delZSet(CacheConst.PRT_CATEGORY_ORDER_PRICE_ZSET + categoryId, "P" + spuDO.getId()); cacheComponent.delZSet(CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + categoryId, "P" + spuDO.getId()); } cacheComponent.delZSet(CacheConst.PRT_CATEGORY_ORDER_ID_ZSET + null, "P" + spuDO.getId()); cacheComponent.delZSet(CacheConst.PRT_CATEGORY_ORDER_PRICE_ZSET + null, "P" + spuDO.getId()); cacheComponent.delZSet(CacheConst.PRT_CATEGORY_ORDER_SALES_ZSET + null, "P" + spuDO.getId()); // 2. 删除基本信息Hash表 cacheComponent.delHashKey(CacheConst.PRT_SPU_HASH_BUCKET, "P" + spuDO.getId()); // 3. 删除商品详情信息Hash表 cacheComponent.delHashKey(CacheConst.PRT_SPU_DETAIL_HASH_BUCKET, "P" + spuDO.getId()); } }