1)在第一页面的时候会发起两次请求,第一次是查询商品分类,第二次是查询规格参数
2)修改SpecificationController当中queryParamByGid方法的参数以及方法名称
/*
根据参数的集合
*/
@GetMapping(“params”)
public ResponseEntity<List> queryParamList(
@RequestParam(value = “gid”,required = false) Long gid,
@RequestParam(value = “cid”,required = false) Long cid, //require当前参数设置可有可无
@RequestParam(value = “searching”,required = false) boolean searching //searching设置是否搜索
){
return ResponseEntity.ok(specificationService.queryParamList(gid,cid,searching));
}
3)完善specificationService
public List queryParamList(Long gid,long cid,boolean searching) {
SpecParam specParam = new SpecParam();
specParam.setGroupId(gid);
specParam.setCid(cid);
specParam.setSearching(searching);
List list = specParamMapper.select(specParam);
if(CollectionUtils.isEmpty(list)){
// 没有查询到
throw new LyException(ExceptionEnum.SPEC_PARAM_NOT_FOND);
}
return list;
}
4)运行测试
下一步
(5)实现表单提交(后台实现)
1)分析提交的参数
2)编写对应的实体类
a、Sku
package com.leyou.item.pojo;
import com.sun.org.apache.xpath.internal.operations.Bool;
import tk.mybatis.mapper.annotation.KeySql;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.Date;
@Table(name = “tb_sku”)
@Data
public class Sku {
@Id
@KeySql(useGeneratedKeys = true)
private Long id;
private Long spuId;
private String title;
private String images;
private Long price;
private String ownSpec;//商品特殊规格的键值对
private String indexes;//商品特殊规格下标
private Boolean enable;//是否有效,逻辑删除用
private Date createTime; //创建时间
private Date lastUpdateTime; //最后修改时间
@Transient
private Integer stock;//库存
}
b、Stock
package com.leyou.item.pojo;
import javax.persistence.Id;
import javax.persistence.Table;
@Table(name = “tb_stock”)
@Data
public class Stock {
@Id
private Long skuId;
private Integer seckillStock;//秒杀可以用缓存
private Integer seckillTotal;//已经秒杀数量
private Integer stock;//正常库存
}
c、完善Spu用于接收页面的参数
package com.leyou.item.pojo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.util.Date;
import java.util.List;
@Table(name = “tb_spu”)
@Data
public class Spu {
@Id
@KeySql(useGeneratedKeys = true)
private Long id;
private Long brandId;
private Long cid1; //1级类目
private Long cid2; //2级类目
private Long cid3; //2级类目
private String title;//标题
private String subTitle;//子标题
private Boolean saleable;//是否上架
@JsonIgnore //设置返回页面数据的时候,忽略当前字段
private Boolean valid;//是否有效。逻辑删除用
private Date createTime;//创建时间
@JsonIgnore //设置返回页面数据的时候,忽略当前字段
private Date lastUpdateTime;//最后修改时间
@Transient //Transient声明当前字段不是数据对应的字段
private String cname;
@Transient //Transient声明当前字段不是数据库对应的字段
private String bname;
@Transient //Transient声明当前字段不是数据库对应的字段
private List skus;
@Transient
private SpuDetail spuDetail;
}
3)创建对应的Mapper
a)SkuMapper
package com.leyou.item.mapper;
import com.leyou.item.pojo.Sku;
import tk.mybatis.mapper.common.Mapper;
public interface SkuMapper extends Mapper {
}
b)SkuMapper
package com.leyou.item.mapper;
import com.leyou.item.pojo.Stock;
import tk.mybatis.mapper.common.Mapper;
public interface StockMapper extends Mapper {
}
4)对应的Service,不需要直接使用GoodsService
5)GoodsController创建saveGoods方法
/*
商品的新增
*/
@PostMapping(“goods”)
public ResponseEntity saveGoods(@RequestBody Spu spu){
goodsService.saveGoods(spu);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
6)完善Service层
a、设置新增商品失败的枚举
GOODS_SAVE_ERROR(500,“新增商品失败”),
b、完善SpuDetail的get和set方法
package com.leyou.item.pojo;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
@Data
@Table(name = “tb_spu_detail”)
public class SpuDetail {
@Id
private Long spuId;//对应SPU的id
private String description ; //商品描述
private String specialSpec ; //商品特殊规格的名称及可选值模板
private String genericSpec; //商品的全局规格属性
private String packingList; //包装清单
private String afterService ; //售后服务
}
c、扩展 StockMapper
-
在common当中定义一个通用的Mapper
-
- 先引入依赖
-
- 定义通用Mapper
package com.leyou.common.mapper;
import tk.mybatis.mapper.additional.idlist.IdListMapper;
import tk.mybatis.mapper.additional.insert.InsertListMapper;
import tk.mybatis.mapper.annotation.RegisterMapper;
import tk.mybatis.mapper.common.Mapper;
@RegisterMapper
public interface BaseMapper extends Mapper, IdListMapper<T,Long>, InsertListMapper {
}
-
- 完善StockMapper当中继承自定义的BaseMapper(注意包路径)
package com.leyou.item.mapper;
import com.leyou.common.mapper.BaseMapper;
import com.leyou.item.pojo.Stock;
public interface StockMapper extends BaseMapper {
}
d、完善GoodsService
@Transient
public void saveGoods(Spu spu) {
//新增SPU
spu.setId(null);
spu.setCreateTime(new Date());
spu.setLastUpdateTime(spu.getCreateTime());
spu.setSaleable(true);
spu.setValid(false);//设置默认不删除
int count = spuMapper.insert(spu);
if(count != 1){
throw new LyException(ExceptionEnum.GOODS_SAVE_ERROR);
}
//新增spu_detail
SpuDetail spuDetail = spu.getSpuDetail();
spuDetail.setSpuId(spu.getId());//spu新增完善会回显,然后就有spu.getId())
spuDetailMapper.insert(spuDetail);
//定义库存的集合
List stockList = new ArrayList();
//新增sku
List skus = spu.getSkus();
for (Sku sku : skus) {
sku.setCreateTime(new Date());
sku.setLastUpdateTime(sku.getCreateTime());
sku.setSpuId(spu.getId());
count = skuMapper.insert(sku);
if(count != 1){
throw new LyException(ExceptionEnum.GOODS_SAVE_ERROR);
}
//将库存放入到库存集合当中
Stock stock = new Stock();
stock.setSkuId(sku.getId());
stock.setStock(sku.getStock());
stockList.add(stock);
}
//批量新增库存
count = stockMapper.insertList(stockList);
if(count != stockList.size()){
throw new LyException(ExceptionEnum.GOODS_SAVE_ERROR);
}
}
7)运行测试
- 点击保存后运行报错
-
因为通用mapper继承的InsertListMapper接口是不支持没有自增注解的类批量添加的
-
修改StockMapper继承additional下的InsertListMapper
package com.leyou.item.mapper;
import com.leyou.item.pojo.Stock;
import tk.mybatis.mapper.additional.insert.InsertListMapper;
public interface StockMapper extends InsertListMapper {
}
- 运行测试
保存成功
@PostMapping(“param”)
public ResponseEntity addSpecParam(@RequestBody SpecParam specParam){
specificationService.addSpecParam(specParam);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
public void addSpecParam(SpecParam specParam) {
int count = specParamMapper.insert(specParam);
if(count <= 0){
throw new LyException(ExceptionEnum.BRAND_SAVE_ERROR);
}
}
0、页面分析,发起请求参数为当前商品的id
1、点击修改按钮商品回显(查询SPU)
(1)完善GoodsController
@GetMapping(“/spu/detail/{id}”)
public ResponseEntity queryDetailById(@PathVariable(“id”) Long spuId){
return ResponseEntity.ok(goodsService.queryDetailById(spuId));
}
(2)完善goodsService
public SpuDetail queryDetailById(Long spuId) {
SpuDetail spuDetail = spuDetailMapper.selectByPrimaryKey(spuId);
if(spuDetail == null){
throw new LyException(ExceptionEnum.GOODS_NOT_FOND);
}
return spuDetail;
}
发送成功
但是第二个请求缺失败了
2、点击修改按钮商品回显(查询SKU)
1)完善GoodsController
/*
通过spu查询其所有sku
*/
@GetMapping(“sku/list”)
public ResponseEntity<List> querySkuBySpuId(@RequestParam(“id”) Long spuId){
return ResponseEntity.ok(goodsService.querySkuBySpuId(spuId));
}
2)完善goodsService
创建对应抛出的异常
GOODS_SKU_NOT_FOND(404,“商品SKU不存在”),
GOODS_STOCK_NOT_FOND(404,“商品库存存在”),
public List querySkuBySpuId(Long spuId) {
//查询SKU
Sku sku = new Sku();
sku.setSpuId(spuId);
List list = skuMapper.select(sku);
if(CollectionUtils.isEmpty(list)){
throw new LyException(ExceptionEnum.GOODS_SKU_NOT_FOND);
}
//查询库存方式一
for (Sku s : list) {
Stock stock = stockMapper.selectByPrimaryKey(s.getId());
if(stock == null){
throw new LyException(ExceptionEnum.GOODS_STOCK_NOT_FOND);
}
s.setStock(stock.getStock());
}
return list;
}
3)运行并测试
3、修改数据并保存数据
(1)完善GoodsController
/*
商品的修改
*/
@PutMapping(“goods”)
public ResponseEntity updateGoods(@RequestBody Spu spu){
goodsService.updateGoods(spu);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
(2)完善goodsService
1)创建商品更新失败的枚举
GOODS_UPDATE_ERROR(500,“更新商品失败”),
2)完善updateGoods方法
public void updateGoods(Spu spu) {
//删除SKU
Sku sku = new Sku();
sku.setSpuId(spu.getId());
//查询sku
List skuList = skuMapper.select(sku);
if(!CollectionUtils.isEmpty(skuList)){
//删除sku
skuMapper.delete(sku);
//skuList.stream().map(Sku::getId).collect(Collectors.toList());
//代码解析.stream()将集合转换为流,map将集合当中的的所有id取出转换为集合
// 删除stock
List ids = skuList.stream().map(Sku::getId).collect(Collectors.toList());
stockMapper.deleteByIdList(ids);
}
//修改spu
spu.setValid(null);//是否有效设置为空
spu.setSaleable(null);
spu.setLastUpdateTime(new Date());
spu.setLastUpdateTime(null);
int count = spuMapper.updateByPrimaryKeySelective(spu);
if(count != 1){
throw new LyException(ExceptionEnum.GOODS_UPDATE_ERROR);
}
//修改detail
count = spuDetailMapper.updateByPrimaryKeySelective(spu.getSpuDetail());
if(count != 1){
throw new LyException(ExceptionEnum.GOODS_UPDATE_ERROR);
}
//新增sku和stock
}
3)封装新增sku和stock的方法
将当前内容进行封装
public void saveSkuAndStock(Spu spu){
int count;
//定义库存的集合
List stockList = new ArrayList();
//新增sku
List skus = spu.getSkus();
for (Sku sku : skus) {
sku.setCreateTime(new Date());
sku.setLastUpdateTime(sku.getCreateTime());
sku.setSpuId(spu.getId());
count = skuMapper.insert(sku);
if(count != 1){
throw new LyException(ExceptionEnum.GOODS_SAVE_ERROR);
}
//将库存放入到库存集合当中
Stock stock = new Stock();
stock.setSkuId(sku.getId());
stock.setStock(sku.getStock());
stockList.add(stock);
}
//批量新增库存
count = stockMapper.insertList(stockList);
if(count != stockList.size()){
throw new LyException(ExceptionEnum.GOODS_SAVE_ERROR);
}
}
全部代码
package com.leyou.item.service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import com.leyou.common.vo.PageResult;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.mapper.StockMapper;
import com.leyou.item.pojo.*;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.weaver.ast.Var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;
import java.beans.Transient;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
public class GoodsService {
@Autowired
private SpuMapper spuMapper;
@Autowired
private SpuDetailMapper spuDetailMapper;
@Autowired
private CategoryService categoryService;
@Autowired
private SkuMapper skuMapper;
@Autowired
private BrandService brandService;
@Autowired
private StockMapper stockMapper;
public PageResult querySpuByPage(Integer page, Integer rows, Boolean saleable, String key) {
//分页
PageHelper.startPage(page,rows);
//过滤
Example example = new Example(Spu.class);
Example.Criteria criteria = example.createCriteria();
//搜索条件过滤
if(StringUtils.isNotBlank(key)){
criteria.andLike(“title”,“%”+key+“%”);//第一个参数的数据对应的字段,第二个为页面传入的参数的值
}
//上下架过滤
if(saleable != null){
criteria.andEqualTo(“saleable”,saleable);
}
//设置默认排序方式为商品的更新时间
example.setOrderByClause(“last_update_time DESC”);
//查询
List spus = spuMapper.selectByExample(example);
if(CollectionUtils.isEmpty(spus)){
throw new LyException(ExceptionEnum.GOODS_NOT_FOND);
}
//解析父类和品牌的名称
loadCategoryAndBrandName(spus);
//解析分页的结果
PageInfo info = new PageInfo<>(spus);
return new PageResult<>(info.getTotal(),spus);//将分页信息和结果集合放入PageResult当前返回到页面
}
private void loadCategoryAndBrandName(List spus) {
for (Spu spu : spus) {
//处理父类名称
//Arrays.asList直接将参数序列化为集合
List categorylist = categoryService.queryByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
//将categorylist变为字符串平均
//提取List对象的某getName列值及排重
Stream stringStream = categorylist.stream().map(Category::getName);
//对返回的字符串集合转换为String类型的name集合
List namelist = stringStream.collect(Collectors.toList());
//将集合以/为间隔拼接为字符串
spu.setCname(StringUtils.join(namelist,“/”));
//处理品牌名称
spu.setBname(brandService.queryById(spu.getBrandId()).getName());
}
}
@Transient
public void saveGoods(Spu spu) {
//新增SPU
spu.setId(null);
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
CategoryAndBrandName(spus);
//解析分页的结果
PageInfo info = new PageInfo<>(spus);
return new PageResult<>(info.getTotal(),spus);//将分页信息和结果集合放入PageResult当前返回到页面
}
private void loadCategoryAndBrandName(List spus) {
for (Spu spu : spus) {
//处理父类名称
//Arrays.asList直接将参数序列化为集合
List categorylist = categoryService.queryByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
//将categorylist变为字符串平均
//提取List对象的某getName列值及排重
Stream stringStream = categorylist.stream().map(Category::getName);
//对返回的字符串集合转换为String类型的name集合
List namelist = stringStream.collect(Collectors.toList());
//将集合以/为间隔拼接为字符串
spu.setCname(StringUtils.join(namelist,“/”));
//处理品牌名称
spu.setBname(brandService.queryById(spu.getBrandId()).getName());
}
}
@Transient
public void saveGoods(Spu spu) {
//新增SPU
spu.setId(null);
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-DVEAgL1U-1714921876654)]
[外链图片转存中…(img-iA68kXWu-1714921876654)]
[外链图片转存中…(img-1xhf0dg2-1714921876654)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!