【 后台提供查询接口 】

前台页面已经准备好,接下来就是后台提供数据接口了。

1、数据库表

CREATE TABLE `tb_brand` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '品牌id',
  `name` varchar(50) NOT NULL COMMENT '品牌名称',
  `image` varchar(200) DEFAULT '' COMMENT '品牌图片地址',
  `letter` char(1) DEFAULT '' COMMENT '品牌的首字母',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=325400 DEFAULT CHARSET=utf8 COMMENT='品牌表,一个品牌下有多个商品(spu),一对多关系';

简单的四个字段,不多解释。

这里需要注意的是,品牌和商品分类之间是多对多关系。因此我们有一张中间表,来维护两者间关系:

CREATE TABLE `tb_category_brand` (
  `category_id` bigint(20) NOT NULL COMMENT '商品类目id',
  `brand_id` bigint(20) NOT NULL COMMENT '品牌id',
  PRIMARY KEY (`category_id`,`brand_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品分类和品牌的中间表,两者是多对多关系';

但是,你可能会发现,这张表中并没有设置外键约束,似乎与数据库的设计范式不符。为什么这么做?

  • 外键会严重影响数据库读写的效率
  • 数据删除时会比较麻烦

在电商行业,性能是非常重要的。我们宁可在代码中通过逻辑来维护表关系,也不设置外键。

2、实体类

在这里插入图片描述

package com.leyou.item.pojo;

import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;

import javax.persistence.Id;
import javax.persistence.Table;

@Table(name = "tb_brand")
@Data
public class Brand {

    @Id
    @KeySql(useGeneratedKeys = true)
    private Long id;
    private String name;// 品牌名称
    private String image;// 品牌图片
    private Character letter;
}

3、mapper

通用 mapper 来简化开发:

package com.leyou.item.mapper;

import com.leyou.item.pojo.Brand;
import tk.mybatis.mapper.common.Mapper;

public interface BrandMapper extends Mapper<Brand> {
}

4、controller

编写 controller 先思考四个问题,这次没有前端代码,需要我们自己来设定

  • 请求方式:查询,肯定是Get

  • 请求路径:分页查询,/brand/page

  • 请求参数:根据我们刚才编写的页面,有分页功能,有排序功能,有搜索过滤功能,因此至少要有5个参数:

    • page:当前页,int
    • rows:每页大小,int
    • sortBy:排序字段,String
    • desc:是否为降序,boolean
    • key:搜索关键词,String
  • 响应结果:分页结果一般至少需要两个数据

    • total:总条数
    • items:当前页数据
    • totalPage:有些还需要总页数

    这里我们封装一个类,来表示分页结果:

package com.leyou.common.vo;

import lombok.Data;

import java.util.List;

@Data
public class PageResult<T> {
    private Long total;// 总条数
    private Integer totalPage;// 总页数
    private List<T> items;// 当前页数据

    public PageResult(){}

    public PageResult(Long total, List<T> items){
        this.total = total;
        this.items = items;
    }

    public PageResult(Long total,Integer totalPage, List<T> items){
        this.total = total;
        this.totalPage = totalPage;
        this.items = items;
    }

}

另外,这个PageResult以后可能在其它项目中也有需求,因此我们将其抽取到ly-common中,提高复用性:

在这里插入图片描述

接下来,我们编写 Controller

package com.leyou.item.controller;

import com.leyou.common.vo.PageResult;
import com.leyou.item.pojo.Brand;
import com.leyou.item.service.BrandService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("brand")
public class BrandController {

    @Autowired
    private BrandService brandService;

    /**
     * 分页查询品牌
     * @param page
     * @param rows
     * @param sortBy
     * @param desc
     * @param key
     * @return
     */
    @GetMapping("page")
    public ResponseEntity<PageResult<Brand>> queryBrandByPage(
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            @RequestParam(value = "rows", defaultValue = "5") Integer rows,
            @RequestParam(value = "sortBy", required = false) String sortBy,
            @RequestParam(value = "desc", defaultValue = "false") Boolean desc,
            @RequestParam(value = "key", required = false) String key) {
        PageResult<Brand> result = this.brandService.queryBrandByPage(page,rows,sortBy,desc, key);
        return ResponseEntity.ok(result);
    }

}

5、Service

package com.leyou.item.service;

import com.github.pagehelper.Page;
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.BrandMapper;
import com.leyou.item.pojo.Brand;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.List;

@Service
public class BrandService {

    @Autowired
    private BrandMapper brandMapper;

    public PageResult<Brand> queryBrandByPage(
            Integer page, Integer rows, String sortBy, Boolean desc, String key) {
        // 开始分页
        PageHelper.startPage(page, rows);
        // 过滤
        Example example = new Example(Brand.class);
        if (StringUtils.isNotBlank(key)) {
            example.createCriteria().orLike("name", "%" + key + "%")
                    .orEqualTo("letter", key.toUpperCase());
        }
        if (StringUtils.isNotBlank(sortBy)) {
            // 排序
            String orderByClause = sortBy + (desc ? " DESC" : " ASC");
            example.setOrderByClause(orderByClause);
        }
        // 查询
        List<Brand> list = brandMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(list)){
            throw new LyException(ExceptionEnum.BRAND_NOT_FOUND);
        }
        //解析分页结果
        PageInfo<Brand> pageInfo = new PageInfo<>(list);
        // 返回结果
        return new PageResult<>(pageInfo.getTotal(), list);
    }

}

在这里插入图片描述

完整结构:

在这里插入图片描述

6、测试

通过浏览器访问试试:http://api.leyou.com/api/item/brand/page

在这里插入图片描述

可以配置打印 mybatis 的日志信息

ly-item-service 里面添加配置:

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

会在控制台打印 sql 语句

2019-03-10 17:19:00.201  INFO 236 --- [nio-8081-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2019-03-10 17:19:00.201  INFO 236 --- [nio-8081-exec-2] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2019-03-10 17:19:00.234  INFO 236 --- [nio-8081-exec-2] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 33 ms
Creating a new SqlSession
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@651968aa] was not registered for synchronization because synchronization is not active
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2de986b5] was not registered for synchronization because synchronization is not active
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3f167967] was not registered for synchronization because synchronization is not active
2019-03-10 17:19:00.326  INFO 236 --- [nio-8081-exec-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2019-03-10 17:19:01.471  INFO 236 --- [nio-8081-exec-2] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
JDBC Connection [HikariProxyConnection@1314791003 wrapping com.mysql.jdbc.JDBC4Connection@50363de] will not be managed by Spring
==>  Preparing: SELECT id,name,parent_id,is_parent,sort FROM tb_category WHERE parent_id = ? 
==> Parameters: 0(Long)
<==    Columns: id, name, parent_id, is_parent, sort
<==        Row: 1, 图书、音像、电子书刊, 0, 1, 1
<==        Row: 74, 手机, 0, 1, 2
<==        Row: 103, 家用电器, 0, 1, 3
<==        Row: 202, 数码, 0, 1, 4
<==        Row: 264, 家居家装, 0, 1, 5
<==        Row: 322, 电脑办公, 0, 1, 6
<==        Row: 417, 厨具, 0, 1, 7
<==        Row: 471, 个护化妆, 0, 1, 8
<==        Row: 548, 服饰内衣, 0, 1, 9
<==        Row: 666, 钟表, 0, 1, 10
<==        Row: 680, 鞋靴, 0, 1, 11
<==        Row: 718, 母婴, 0, 1, 12
<==        Row: 808, 礼品箱包, 0, 1, 13
<==        Row: 871, 食品饮料、保健食品, 0, 1, 14
<==        Row: 931, 珠宝, 0, 1, 15
<==        Row: 1020, 汽车用品, 0, 1, 16
<==        Row: 1117, 运动健康, 0, 1, 17
<==        Row: 1230, 玩具乐器, 0, 1, 18
<==        Row: 1293, 彩票、旅行、充值、票务, 0, 1, 19
<==        Row: 1329, 生鲜, 0, 1, 20
<==        Row: 1401, 整车, 0, 1, 21
<==      Total: 21
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3f167967]
JDBC Connection [HikariProxyConnection@2071312311 wrapping com.mysql.jdbc.JDBC4Connection@50363de] will not be managed by Spring
==>  Preparing: SELECT count(0) FROM tb_brand 
==> Parameters: 
<==    Columns: count(0)
<==        Row: 165
<==      Total: 1
==>  Preparing: SELECT id,name,image,letter FROM tb_brand order by id ASC LIMIT ? 
==> Parameters: 5(Integer)
<==    Columns: id, name, image, letter
<==        Row: 1115, HTC, , H
<==        Row: 1528, LG, , L
<==        Row: 1912, NEC, , N
<==        Row: 2032, OPPO, http://img10.360buyimg.com/popshop/jfs/t2119/133/2264148064/4303/b8ab3755/56b2f385N8e4eb051.jpg, O
<==        Row: 2505, TCL, , T
<==      Total: 5
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@651968aa]
JDBC Connection [HikariProxyConnection@1503963007 wrapping com.mysql.jdbc.JDBC4Connection@50363de] will not be managed by Spring
==>  Preparing: SELECT count(0) FROM tb_brand 
==> Parameters: 
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16c31a01] was not registered for synchronization because synchronization is not active
<==    Columns: count(0)
<==        Row: 165
<==      Total: 1
==>  Preparing: SELECT id,name,image,letter FROM tb_brand order by id ASC LIMIT ? 
==> Parameters: 5(Integer)
<==    Columns: id, name, image, letter
<==        Row: 1115, HTC, , H
<==        Row: 1528, LG, , L
<==        Row: 1912, NEC, , N
<==        Row: 2032, OPPO, http://img10.360buyimg.com/popshop/jfs/t2119/133/2264148064/4303/b8ab3755/56b2f385N8e4eb051.jpg, O
<==        Row: 2505, TCL, , T
<==      Total: 5
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2de986b5]
JDBC Connection [HikariProxyConnection@473657713 wrapping com.mysql.jdbc.JDBC4Connection@50363de] will not be managed by Spring
==>  Preparing: SELECT count(0) FROM tb_brand 
==> Parameters: 
<==    Columns: count(0)
<==        Row: 165
<==      Total: 1
==>  Preparing: SELECT id,name,image,letter FROM tb_brand order by id ASC LIMIT ? 
==> Parameters: 5(Integer)
<==    Columns: id, name, image, letter
<==        Row: 1115, HTC, , H
<==        Row: 1528, LG, , L
<==        Row: 1912, NEC, , N
<==        Row: 2032, OPPO, http://img10.360buyimg.com/popshop/jfs/t2119/133/2264148064/4303/b8ab3755/56b2f385N8e4eb051.jpg, O
<==        Row: 2505, TCL, , T
<==      Total: 5
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16c31a01]

猜你喜欢

转载自blog.csdn.net/weixin_42112635/article/details/88377968
今日推荐