史上最强项目实战(二十三)——商品类别的增删改查

写之前纠结了一小会,纠结要不要去哪个网站截个图出来给大家看看啥事商品类别。但后来一想,活到这个年纪,如果还不知道什么是商品类别的话那就有点说不过去了。也罢虽然没有图来得直接,但文字应该也能表达清楚。举个例子:电子设备包括手机、智能手表、电脑等等,在这里电子设备就是一个商品类别,手机、智能手表、电脑也都是一个商品类别,而电子设备是手机这个类别的父类别。一个子类别只能有一个父类别,而一个父类别可以有多个子类别,这么说应该清楚了吧。废话不多说,赶紧今天的开发。

1. 数据结构

因为商品分类会有层级关系,因此这里我们加入了parent_id字段,对本表中的其它分类进行自关联。

CREATE TABLE `tb_category` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '类目id',
  `name` varchar(20) NOT NULL COMMENT '类目名称',
  `parent_id` bigint(20) NOT NULL COMMENT '父类目id,顶级类目填0',
  `is_parent` tinyint(1) NOT NULL COMMENT '是否为父节点,0为否,1为是',
  `sort` int(4) NOT NULL COMMENT '排序指数,越小越靠前',
  PRIMARY KEY (`id`),
  KEY `key_parent_id` (`parent_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1424 DEFAULT CHARSET=utf8 COMMENT='商品类目表,类目和商品(spu)是一对多关系,类目与品牌是多对多关系';

2. pojo实体类

没啥特殊的骚操作,字段也很简单,直接看代码吧。

@Data
@Entity
@Table(name = "tb_category")
@ApiModel(description = "商品类别")
public class Category {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @ApiModelProperty(value = "唯一标识id", dataType = "Long")
    private Long id;

    @NotBlank
    @Length(max = 20, message = "类别名称,不允许超过20位长度")
    @ApiModelProperty(value = "类别名称", dataType = "String")
    private String name;

    @ApiModelProperty(value = "父类别id", dataType = "String")
    private Long parentId;

    @NotNull
    @ApiModelProperty(value = "是否是父类别", dataType = "Boolean")
    private Boolean isParent;

    @NotNull
    @ApiModelProperty(value = "序列", dataType = "Integer")
    private Integer sort;
}

3. repository

public interface CategoryRepository extends CrudRepository<Category, Long>, JpaSpecificationExecutor<Category> {

    /**
     * 根据类别名称查找
     *
     * @param name 类别名称
     * @return
     */
    Category getByName(String name);

    /**
     * 查父商品类别下的所有子类别
     *
     * @param parentId 父类别id
     * @return
     */
    List<Category> findAllByParentId(Long parentId);
}

4. service

今天只实现最简单的功能:增删改查。

@Service
public class CategoryService {

    @Autowired
    private CategoryRepository categoryRepository;

    public Category save(Category entity) {
        Category category = categoryRepository.getByName(entity.getName());
        if (entity.getId() == null || entity.getId() != category.getId()) {
            LeyouExceptionCast.cast(ItemResultCode.PRODUCT_CATEGORY_NAME_IS_EXIST);
        }
        return categoryRepository.save(entity);
    }

    public void deleteById(Long id) {
        // 判断id对应的实体是否存在
        boolean isExist = categoryRepository.existsById(id);
        if (isExist == false) {
            LeyouExceptionCast.cast(ItemResultCode.PRODUCT_CATEGORY_IS_NOT_EXIST);
        }
        categoryRepository.deleteById(id);
    }

    public Category findById(Long id) {
        Optional<Category> optional = categoryRepository.findById(id);
        return optional.isPresent() ? optional.get() : null;
    }

    public Iterable<Category> findAllById(List<Long> ids) {
        return categoryRepository.findAllById(ids);
    }

    public List<Category> findAllByParentId(Long parentId) {
        return categoryRepository.findAllByParentId(parentId);
    }
    
    public Page<Category> query(int page, int pageSize) {
        PageRequest pageRequest = PageRequest.of(page, pageSize);
        return categoryRepository.findAll(new Specification<Category>() {
            @Override
            public Predicate toPredicate(Root<Category> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                return null;
            }
        }, pageRequest);
    }
}

5. controller

有了业务层接口,那控制器的代码自然就很简单的,即针对业务层的每一个方法提供对外接口即可。

@Api(value = "商品类别管理")
@RestController
@RequestMapping("/item/category")
public class CategoryController {

    @Autowired
    private CategoryService categoryService;

    @PostMapping
    @ApiOperation(value = "新增商品类别", httpMethod = "POST")
    @ApiImplicitParam(name = "entity", value = "商品类别", required = true, dataType = "Category")
    public ResponseResult save(@Valid @RequestBody Category entity) {
        return new ResponseResult(CommonResultCode.SUCCESS, categoryService.save(entity));
    }

    @DeleteMapping("/{id}")
    @ApiOperation(value = "删除商品类别", httpMethod = "DELETE")
    @ApiImplicitParam(name = "id", value = "类别id", required = true, dataType = "Long", paramType = "path")
    public ResponseResult deleteById(@PathVariable("id") Long id) {
        categoryService.deleteById(id);
        return new ResponseResult(CommonResultCode.SUCCESS);
    }

    @GetMapping("/{id}")
    @ApiOperation(value = "指定唯一标识获取商品类别", httpMethod = "GET")
    @ApiImplicitParam(name = "id", value = "类别id", required = true, dataType = "Long", paramType = "path")
    public ResponseResult findById(@PathVariable("id") Long id) {
        return new ResponseResult(CommonResultCode.SUCCESS, categoryService.findById(id));
    }

    @PostMapping("/ids")
    @ApiOperation(value = "查询id集合的所有商品类别", httpMethod = "POST")
    @ApiImplicitParam(name = "ids", value = "类别ids", required = true, dataType = "List", paramType = "body")
    public ResponseResult findAllById(@RequestBody List<Long> ids) {
        return new ResponseResult(CommonResultCode.SUCCESS, categoryService.findAllById(ids));
    }

    @GetMapping("/p/{parentId}")
    @ApiOperation(value = "查询父类别下的所有子类别", httpMethod = "GET")
    @ApiImplicitParam(name = "parentId", value = "父类别id", required = true, dataType = "Long", paramType = "path")
    public ResponseResult findAllByParentId(@PathVariable("parentId") Long parentId) {
        return new ResponseResult(CommonResultCode.SUCCESS, categoryService.findAllByParentId(parentId));
    }

    @PostMapping("/{page}/{pageSize}")
    @ApiOperation(value = "查询商品类别", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "当前页", required = true, dataType = "int", paramType = "path"),
            @ApiImplicitParam(name = "pageSize", value = "页大小", required = true, dataType = "int", paramType = "path")
    })
    public ResponseResult query(@PathVariable("page") int page, @PathVariable("pageSize") int pageSize) {
        Page<Category> categories = categoryService.query(page, pageSize);
        QueryResult<Category> queryResult = new QueryResult<>();
        queryResult.setList(categories.getContent());
        queryResult.setTotal(categories.getTotalElements());
        return new ResponseResult(CommonResultCode.SUCCESS, queryResult);
    }
}

大功告成,代码已经写完了。然后就是测试,其实这部分测试也很简单,感觉没啥好测的。因为我们集成了Swagger,所以访问Swagger-UI界面把数据写进去,然后测就完了。基本上都是傻瓜式的操作,所以我们这里就不测了,万一……以后用到某个接口碰到了bug,我们再来修复。当然还有一点,Swagger-UI的访问地址……http://localhost:9040/swagger-ui.html拿好不谢。

但是这里再说一下,我觉得吧,代码虽然写完了,但是有两个地方是我之后想要去重构的。第一:加缓存;第二:把增删改查的业务层实现抽取出来,因为我们后面还会有品牌的增删改查、商品Spu的增删改查等等,这类基础资料的增删改查写多了还真有点烦人,作为一个高级软件工程师,我们是绝对不能容忍写这么低级的业务代码的。

当然这都是后话了,至于什么时候去重构,拿个小本本先记着,我们等项目所有的基本功能都实现了再回头考虑重构,哪里不爽改哪里。

——End——
更多详情,可扫码关注微信公众号哦。

在这里插入图片描述

发布了150 篇原创文章 · 获赞 35 · 访问量 9万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览