第1关:分页查询所有商品
任务描述
本关任务:实现分页查询所有商品功能。
相关知识
为了完成本关任务,你需要掌握:
- 什么是分页查询?
- 为什么使用分页查询?
- 分页查询的实现。
什么是分页查询
- 逻辑分页:一次性将所有数据查询出来,保存到 List 集合中,后续,如果有分页请求,再对 List 集合进行拆分。 优点:减少了操作数据库的次数。 缺点:单次查询数据库的时间过长。
- 物理分页:不是一次性将所有数据全部查询出来.查询第一页:发送一条查询 10 条的 SQL 语句.查询下 一页数据:又发送一条查询后 10 条的 SQL 语句。 优点:单词查询数据库的时间非常短。 缺点:操作数据库的次数增加。 效果图如下:
为什么使用分页查询
-
当数据量过大时,可能会导致各种各样的问题发生,例如:服务器资源被耗尽,因数据传输量过大而使处理超时,等等。最终都会导致查询无法完成。
-
解决这个问题的一个策略就是“分页查询”,也就是说不要一次性查询所有的数据,每次只查询一“页“的数据。这样分批次地进行处理,可以呈现出很好的用户体验,对服务器资源的消耗也不大。
Mybatis 分页查询的实现
- dao 层代码: 先查询所有商品的总数量,其中 status=1 代表正在使用的商品。
select count(1) from product where status=1
select * from product where status=1 limit #{filter},#{pageSize}
- service 层: 可以先去 redis 中查询总条数,如果没有再去数据库中查询并存入 redis 中,总条数可用来计算总页数。
Object allPageCount=redisTemplate.opsForValue().get("allPageCount");
int count=0;
//查询数据总条数
if (allPageCount==null){
count=productDao.getAllProductCount();
redisTemplate.opsForValue().set("allPageCount",count);
}else {
count=Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get("allPageCount")));
}
//数据总条数存入page对象
page.setCount(count);
//设置当前页数
page.setCurrPage(currentPage);
//设置每页条数
page.setPageSize(pageSize);
//设置过滤条数过滤前面页面数据
page.setFilterCount((page.getCurrPage()-1)*page.getPageSize());
//设置总页数,总页数+每页条数-1再运算可使总页数向上取整
page.setPageCount((page.getCount()+page.getPageSize()-1)/page.getPageSize());
//设置下一页
page.setNextPage(page.getCurrPage()==page.getPageCount()?page.getCurrPage():page.getCurrPage()+1);
//设置上一页
page.setPrePage(page.getCurrPage()==1?page.getCurrPage():page.getCurrPage()-1);
page.setList(productDao.getAllProduct(page.getFilterCount(),page.getPageSize()));
- 数据库如下:
字段名称 类型 备注 product_id
int(11) NOT NULL AUTO_INCREMENT '商品id' product_name
char(100) NOT NULL '商品名' category_id
int(11) NOT NULL '类型id' product_title
char(30) NOT NULL '商品标题' product_intro
text NOT NULL '商品描述' product_picture
char(200) DEFAULT NULL '商品图片' product_price
decimal(10,2) NOT NULL '商品价格' product_selling_price
decimal(10,2) NOT NULL '商品售价' product_num
int(11) NOT NULL '商品存量' product_sales
int(11) NOT NULL '商品销售数量' status
int(11) DEFAULT NULL '商品状态'
编程要求
在 ProductDao.java、ProductService.java、ProductServiceImpl.java、ProductController.java 中 Begin-End 处补充代码,实现分页查询所有商品功能。
测试说明
平台会对你编写的代码进行测试:发送请求获取数据测试代码是否正确。 预期输入:
{
"currentPage":"1",
"pageSize":"3"
}
预期输出:
{"currPage":1,"prePage":1,"nextPage":2,"count":35,"list":[{"product_id":1,"product_name":"Redmi K30","category_id":1,"product_title":"120Hz流速屏,全速热爱","product_intro":"120Hz高帧率流速屏/ 索尼6400万前后六摄 / 6.67'小孔径全面屏 / 最高可选8GB+256GB大存储 / 高通骁龙730G处理器 / 3D四曲面玻璃机身 / 4500mAh+27W快充 / 多功能NFC","product_picture":"public/imgs/phone/Redmi-k30.png","product_price":2000.00,"product_selling_price":1599.00,"product_num":10,"product_sales":0},{"product_id":2,"product_name":"Redmi K30 5G","category_id":1,"product_title":"双模5G,120Hz流速屏","product_intro":"双模5G / 三路并发 / 高通骁龙765G / 7nm 5G低功耗处理器 / 120Hz高帧率流速屏 / 6.67'小孔径全面屏 / 索尼6400万前后六摄 / 最高可选8GB+256GB大存储 / 4500mAh+30W快充 / 3D四曲面玻璃机身 / 多功能NFC","product_picture":"public/imgs/phone/Redmi-k30-5G.png","product_price":2599.00,"product_selling_price":2599.00,"product_num":10,"product_sales":0},{"product_id":3,"product_name":"小米CC9 Pro","category_id":1,"product_title":"1亿像素,五摄四闪","product_intro":"1亿像素主摄 / 全场景五摄像头 / 四闪光灯 / 3200万自拍 / 10 倍混合光学变焦,50倍数字变焦 / 5260mAh ⼤电量 / 标配 30W疾速快充 / ⼩米⾸款超薄屏下指纹 / 德国莱茵低蓝光认证 / 多功能NFC / 红外万能遥控 / 1216超线性扬声器","product_picture":"public/imgs/phone/Mi-CC9.png","product_price":2799.00,"product_selling_price":2599.00,"product_num":20,"product_sales":0}],"pageSize":3,"pageCount":12,"filterCount":0}
开始你的任务吧,祝你成功!
ProductDao.java
package com.lxc.dao;
import com.lxc.entity.Product;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ProductDao {
//分夜查询商品
/*******************************Begin*******************************/
@Select("select count(1) from product where status=1")
int getAllProductCount();
/*******************************End*******************************/
//查询商品总条数
/*******************************Begin*******************************/
@Select("select * from product where status=1 limit #{filter},#{pageSize}")
List<Product> getAllProduct(int filter, int pageSize);
/*******************************End*******************************/
}
ProductService.java
package com.lxc.service;
import com.lxc.entity.Page;
import com.lxc.entity.Product;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public interface ProductService {
//定义 service 接口
/*******************************Begin*******************************/
Page<Product> getAllProduct(int currentPage, int pageSize);
/*******************************End*******************************/
}
ProductServiceImpl.java
package com.lxc.service.impl;
import com.lxc.dao.ProductDao;
import com.lxc.entity.Page;
import com.lxc.entity.Product;
import com.lxc.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("productService")
public class ProductServiceImpl implements ProductService {
@Autowired
Page<Product> page;
@Autowired
private ProductDao productDao;
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@Override
public Page<Product> getAllProduct(int currentPage, int pageSize) {
Object allPageCount = redisTemplate.opsForValue().get("allPageCount");
int count = 0;
//查询数据总条数
if (allPageCount == null) {
count = productDao.getAllProductCount();
redisTemplate.opsForValue().set("allPageCount", count);
} else {
count = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get("allPageCount")));
}
//数据总条数存入page对象
page.setCount(count);
//设置当前页数
page.setCurrPage(currentPage);
//设置每页条数
page.setPageSize(pageSize);
//设置过滤条数过滤前面页面数据
page.setFilterCount((page.getCurrPage() - 1) * page.getPageSize());
//设置总页数,总页数+每页条数-1再运算可使总页数向上取整
page.setPageCount((page.getCount() + page.getPageSize() - 1) / page.getPageSize());
//设置下一页
page.setNextPage(page.getCurrPage() == page.getPageCount() ? page.getCurrPage() : page.getCurrPage() + 1);
//设置上一页
page.setPrePage(page.getCurrPage() == 1 ? page.getCurrPage() : page.getCurrPage() - 1);
//分页查询商品
List<Product> productList = productDao.getAllProduct(page.getFilterCount(), page.getPageSize());
page.setList(productList);
return page;
}
}
ProductController.java
package com.lxc.controller;
import com.lxc.entity.Page;
import com.lxc.service.ProductService;
import com.lxc.entity.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping(value = "/product")
public class ProductController {
@Autowired
Page<Product> page;
@Autowired
private ProductService productService;
/**
*
* 查询所有商品
* @return
*/
@RequestMapping(value = "/getAllProduct")
public Page<Product> getAllProduct(@RequestBody Map<String, Object> paramMap) {
int currentPage = Integer.parseInt(paramMap.get("currentPage").toString());
int pageSize = Integer.parseInt(paramMap.get("pageSize").toString());
return productService.getAllProduct(currentPage, pageSize);
}
}
Page.java
package com.lxc.entity;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class Page<E> {
//当前页码
private Integer currPage;
//上一页
private Integer prePage;
//下一页
private Integer nextPage;
//查询的数据总条数
private Integer count;
//当前页的数据内容
private List<E> list;
//每页的数据条数
private Integer pageSize;
//总页数
private Integer pageCount;
//过滤条数
private Integer filterCount;
public Integer getCurrPage() {
return currPage;
}
public void setCurrPage(Integer currPage) {
this.currPage = currPage;
}
public Integer getPrePage() {
return prePage;
}
public void setPrePage(Integer prePage) {
this.prePage = prePage;
}
public Integer getNextPage() {
return nextPage;
}
public void setNextPage(Integer nextPage) {
this.nextPage = nextPage;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public List<E> getList() {
return list;
}
public void setList(List<E> list) {
this.list = list;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getPageCount() {
return pageCount;
}
public void setPageCount(Integer pageCount) {
this.pageCount = pageCount;
}
public Integer getFilterCount() {
return filterCount;
}
public void setFilterCount(Integer filterCount) {
this.filterCount = filterCount;
}
}
Product.java
package com.lxc.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class Product implements Serializable {
private int product_id;
private String product_name;
private int category_id;
private String product_title;
private String product_intro;
private String product_picture;
private BigDecimal product_price; //原价
private BigDecimal product_selling_price; //售价
private int product_num;
private int product_sales;
}
第2关:根据类型分页查询商品
任务描述
本关任务:实现分页根据商品类型查询商品功能。
相关知识
为了完成本关任务,你需要掌握:
- 根据商品类型查询商品。
- 代码实现。
根据商品类型查询商品
即点击一个商品类型后分页查询该类商品,如下图:
代码实现
- dao 层: 根据类型Id查询当前类型已上线的总商品数量,status=1 为已上线的:
select count(1) from product where category_id=#{categoryID} and status=1
select * from product where category_id=#{categoryID} and status=1 order by product_sales desc limit #{currentPage},#{pageSize}
- service 层:
//数据总条数存入page对象
page.setCount(productDao.getProductCountByCategory(categoryID));
//设置当前页数
page.setCurrPage(currentPage);
//设置每页条数
page.setPageSize(pageSize);
//设置过滤条数过滤前面页面数据
page.setFilterCount((page.getCurrPage()-1)*page.getPageSize());
//设置总页数,总页数+每页条数-1再运算可使总页数向上取整
page.setPageCount((page.getCount()+page.getPageSize()-1)/page.getPageSize());
//设置下一页
page.setNextPage(page.getCurrPage()==page.getPageCount()?page.getCurrPage():page.getCurrPage()+1);
//设置上一页
page.setPrePage(page.getCurrPage()==1?page.getCurrPage():page.getCurrPage()-1);
page.setList(productDao.getProductByCategory(categoryID,page.getFilterCount(),page.getPageSize()));
- 数据库如下:
字段名称 类型 备注 product_id
int(11) NOT NULL AUTO_INCREMENT '商品id' product_name
char(100) NOT NULL '商品名' category_id
int(11) NOT NULL '类型id' product_title
char(30) NOT NULL '商品标题' product_intro
text NOT NULL '商品描述' product_picture
char(200) DEFAULT NULL '商品图片' product_price
decimal(10,2) NOT NULL '商品价格' product_selling_price
decimal(10,2) NOT NULL '商品售价' product_num
int(11) NOT NULL '商品存量' product_sales
int(11) NOT NULL '商品销售数量' status
int(11) DEFAULT NULL '商品状态'
编程要求
在 ProductDao.java、ProductService.java、ProductServiceImpl.java、ProductController.java 中 Begin-End 处补充代码,实现分页查询所有商品功能。
测试说明
平台会对你编写的代码进行测试:发送请求获取数据测试代码是否正确。 预期输入:
{
"categoryID":"1",
"currentPage":"1",
"pageSize":"3"
}
预期输出:
{"currPage":1,"prePage":1,"nextPage":2,"count":35,"list":[{"product_id":1,"product_name":"Redmi K30","category_id":1,"product_title":"120Hz流速屏,全速热爱","product_intro":"120Hz高帧率流速屏/ 索尼6400万前后六摄 / 6.67'小孔径全面屏 / 最高可选8GB+256GB大存储 / 高通骁龙730G处理器 / 3D四曲面玻璃机身 / 4500mAh+27W快充 / 多功能NFC","product_picture":"public/imgs/phone/Redmi-k30.png","product_price":2000.00,"product_selling_price":1599.00,"product_num":10,"product_sales":0},{"product_id":2,"product_name":"Redmi K30 5G","category_id":1,"product_title":"双模5G,120Hz流速屏","product_intro":"双模5G / 三路并发 / 高通骁龙765G / 7nm 5G低功耗处理器 / 120Hz高帧率流速屏 / 6.67'小孔径全面屏 / 索尼6400万前后六摄 / 最高可选8GB+256GB大存储 / 4500mAh+30W快充 / 3D四曲面玻璃机身 / 多功能NFC","product_picture":"public/imgs/phone/Redmi-k30-5G.png","product_price":2599.00,"product_selling_price":2599.00,"product_num":10,"product_sales":0},{"product_id":3,"product_name":"小米CC9 Pro","category_id":1,"product_title":"1亿像素,五摄四闪","product_intro":"1亿像素主摄 / 全场景五摄像头 / 四闪光灯 / 3200万自拍 / 10 倍混合光学变焦,50倍数字变焦 / 5260mAh ⼤电量 / 标配 30W疾速快充 / ⼩米⾸款超薄屏下指纹 / 德国莱茵低蓝光认证 / 多功能NFC / 红外万能遥控 / 1216超线性扬声器","product_picture":"public/imgs/phone/Mi-CC9.png","product_price":2799.00,"product_selling_price":2599.00,"product_num":20,"product_sales":0}],"pageSize":3,"pageCount":12,"filterCount":0}
开始你的任务吧,祝你成功!
ProductDao.java
package com.lxc.dao;
import com.lxc.entity.Product;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ProductDao {
//根据商品类型 id 分页查询该类型的所有商品
/*******************************Begin*******************************/
@Select("select * from product where category_id=#{categoryID} and status=1 order by product_sales desc limit #{start},#{pageSize}")
List<Product> getProductByCategory(int categoryID, int start, int pageSize);
//根据类型Id查询当前类型的总商品数量
@Select("select count(1) from product where category_id=#{categoryID} and status=1")
int getProductCountByCategory(int categoryID);
/*******************************End*******************************/
}
ProductService.java
package com.lxc.service;
import com.lxc.entity.Page;
import com.lxc.entity.Product;
import org.springframework.stereotype.Component;
@Component
public interface ProductService {
//定义 service 接口
/*******************************Begin*******************************/
Page<Product> getProductByCategory(int categoryID, int currentPage, int pageSize);
/*******************************End*******************************/
}
ProductServiceImpl.java
package com.lxc.service.impl;
import com.lxc.dao.ProductDao;
import com.lxc.entity.Page;
import com.lxc.entity.Product;
import com.lxc.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("productService")
public class ProductServiceImpl implements ProductService {
@Autowired
private Page<Product> page;
@Autowired
private ProductDao productDao;
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@Override
public Page<Product> getProductByCategory(int categoryID, int currentPage, int pageSize) {
//分页逻辑代码
/*******************************Begin*******************************/
List<Product> productList = productDao.getProductByCategory(categoryID, (currentPage-1)*pageSize, pageSize);
int totalCount = productDao.getProductCountByCategory(categoryID);
int filterCount = (currentPage - 1) * pageSize;
int pageCount = (totalCount + pageSize - 1) / pageSize;
page.setList(productList);
page.setCount(totalCount);//数据总条数存入page对象
page.setCurrPage(currentPage);//设置当前页数
page.setPageSize(pageSize);//设置每页条数
page.setFilterCount(filterCount);//设置过滤条数过滤前面页面数据
page.setPageCount(pageCount);//设置总页数
page.setNextPage(currentPage == pageCount ? currentPage : currentPage + 1);//设置下一页
page.setPrePage(currentPage == 1 ? currentPage : currentPage - 1);//设置上一页
return page;
/*******************************End*******************************/
}
}
ProductController.java
package com.lxc.controller;
import com.lxc.entity.Page;
import com.lxc.service.ProductService;
import com.lxc.entity.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping(value = "/product")
public class ProductController {
@Autowired
Page<Product> page;
@Autowired
private ProductService productService;
/**
* 根据类型id 分页查询当前类型商品
* @param paramMap
* @return
*/
@RequestMapping(value = "/getProductByCategory")
public Page<Product> getProductByCategory(@RequestBody Map<String,Object> paramMap){
//接收参数,调用 servie 接口查询方法
/*******************************Begin*******************************/
int categoryID = Integer.parseInt(paramMap.get("categoryID").toString());
int currentPage = Integer.parseInt(paramMap.get("currentPage").toString());
int pageSize = Integer.parseInt(paramMap.get("pageSize").toString());
return productService.getProductByCategory(categoryID, currentPage, pageSize);
/*******************************Begin*******************************/
}
}
Page.java
package com.lxc.entity;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class Page<E> {
//当前页码
private Integer currPage;
//上一页
private Integer prePage;
//下一页
private Integer nextPage;
//查询的数据总条数
private Integer count;
//当前页的数据内容
private List<E> list;
//每页的数据条数
private Integer pageSize;
//总页数
private Integer pageCount;
//过滤条数
private Integer filterCount;
public Integer getCurrPage() {
return currPage;
}
public void setCurrPage(Integer currPage) {
this.currPage = currPage;
}
public Integer getPrePage() {
return prePage;
}
public void setPrePage(Integer prePage) {
this.prePage = prePage;
}
public Integer getNextPage() {
return nextPage;
}
public void setNextPage(Integer nextPage) {
this.nextPage = nextPage;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public List<E> getList() {
return list;
}
public void setList(List<E> list) {
this.list = list;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getPageCount() {
return pageCount;
}
public void setPageCount(Integer pageCount) {
this.pageCount = pageCount;
}
public Integer getFilterCount() {
return filterCount;
}
public void setFilterCount(Integer filterCount) {
this.filterCount = filterCount;
}
}
Product.java
package com.lxc.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class Product implements Serializable {
private int product_id;
private String product_name;
private int category_id;
private String product_title;
private String product_intro;
private String product_picture;
private BigDecimal product_price; //原价
private BigDecimal product_selling_price; //售价
private int product_num;
private int product_sales;
}
Category.java
package com.lxc.entity;
import lombok.Data;
import java.io.Serializable;
/**
* @author liuxianchun
* @date 2021/1/17
* 目录
*/
@Data
public class Category implements Serializable {
private int category_id;
private String category_name;
}
第3关:搜索框关键字查询
任务描述
本关任务:实现搜索框的关键字查询功能。
相关知识
为了完成本关任务,你需要掌握:
- 关键字查询;
- 功能实现。
关键字查询
- 简单的说,关键字就是用户在使用搜索引擎时,输入的能够最大程度概括用户所要查找的信息内容。在搜索引擎优化 SEO 行业谈到的关键字,往往是指网页的核心和主要内容。对于搜索引擎来说,你的网页主要是讲关于哪方面的内容,那个方面就可以归结出一个(更多时候会是多个)关键字。
- “请输入关键字”这个词语许多朋友经常看到,这个词语是一些网站上面的搜索框中看到的,意思是提示你输入你想要搜索的信息的关键字。我们常见的查询如下图: 当然这样一个大型项目是极其复杂的,但我们可以实现一个简单的查询功能,如下图:
功能实现
- sql 语句: 关键字查询其实就是使用 like 的模糊查询,且一般使用 limit 分页查询:
select * from product //从商品表查询数据
where //查询条件
status=1 // status 为 1 代表上线了的商品
and // 并且
product_name like '%${search}%' //商品名字包含查询关键字
or //或者
product_title like '%${search}%' //商品标题包含关键字
or //或者
product_intro like '%${search}%' //商品描述包含关键字
limit #{filterCount} , #{pageSize} //分页查询,过滤 filterCount 条数据,查询 pageSize 条数据
- dao 层: 首先我们要确定通过关键字查询出来的数据条数:
//查询符合条件的商品的数量
@Select("select count(1) from product where status=1 and product_name like '%${search}%' or product_title like '%${search}%' or product_intro like '%${search}%'")
int getProductCountBySearch(String search);
//对上线商品中的商品名,商品标题,商品描述进行关键字对比
@Select("select * from product where status=1 and product_name like '%${search}%' or product_title like '%${search}%' or product_intro like '%${search}%' limit #{filterCount} , #{pageSize}")
List<Product> getProductBySearch(String search,int filterCount,int pageSize);
- service 层代码: 设置分页参数,page 是分页实体类:
//数据总条数存入page对象
page.setCount(productDao.getProductCountBySearch(search));
//设置当前页数
page.setCurrPage(currentPage);
//设置每页条数
page.setPageSize(pageSize);
//设置过滤条数过滤前面页面数据
page.setFilterCount((page.getCurrPage()-1)*page.getPageSize());
//设置总页数,总页数+每页条数-1再运算可使总页数向上取整
page.setPageCount((page.getCount()+page.getPageSize()-1)/page.getPageSize());
//设置下一页
page.setNextPage(page.getCurrPage()==page.getPageCount()?page.getCurrPage():page.getCurrPage()+1);
//设置上一页
page.setPrePage(page.getCurrPage()==1?page.getCurrPage():page.getCurrPage()-1);
page.setList(productDao.getProductBySearch(search,page.getFilterCount(),page.getPageSize()));
- controller 层: 接收参数调用 service 层方法并返回结果集:
String search = String.valueOf(paramMap.get("search"));
int currentPage =Integer.parseInt (String.valueOf(paramMap.get("currentPage")));
int pageSize = Integer.parseInt (String.valueOf(paramMap.get("pageSize")));
//根据关键字搜索所有商品
return productService.getProductBySearch(search,currentPage,pageSize);
- 数据库如下:
字段名称 类型 备注 product_id
int(11) NOT NULL AUTO_INCREMENT '商品id' product_name
char(100) NOT NULL '商品名' category_id
int(11) NOT NULL '类型id' product_title
char(30) NOT NULL '商品标题' product_intro
text NOT NULL '商品描述' product_picture
char(200) DEFAULT NULL '商品图片' product_price
decimal(10,2) NOT NULL '商品价格' product_selling_price
decimal(10,2) NOT NULL '商品售价' product_num
int(11) NOT NULL '商品存量' product_sales
int(11) NOT NULL '商品销售数量' status
int(11) DEFAULT NULL '商品状态'
编程要求
在 ProductDao.java、ProductService.java、ProductServiceImpl.java、ProductController.java 中 Begin-End 处根据提示补充代码。
测试说明
平台会对你编写的代码进行测试:发送请求检验代码是否正确。
请求参数:
{
"search":"手",
"currentPage":"2",
"pageSize":"3"
}
预期输出:
{"currPage":1,"prePage":1,"nextPage":2,"count":4,"list":[{"product_id":19,"product_name":"Redmi K20/ K20 Pro 怪力魔王保护壳","category_id":5,"product_title":"怪力魔王专属定制","product_intro":"优选PC材料,强韧张力,经久耐用 / 精选开孔,全面贴合机身 / 手感轻薄细腻,舒适无负担 / 三款颜色可选,彰显个性,与众不同","product_picture":"public/imgs/accessory/protectingShell-RedMi-K20&pro.png","product_price":39.00,"product_selling_price":39.00,"product_num":20,"product_sales":0},{"product_id":21,"product_name":"小米CC9&小米CC9美图定制版 标准高透贴膜","category_id":6,"product_title":"高清透亮,耐磨性强","product_intro":"耐磨性强,防护更出众 / 疏油疏水,有效抗水抗脏污 / 高清透亮,保留了原生屏幕的亮丽颜色和清晰度 / 操作灵敏,智能吸附 / 进口高端PET材质,裸机般手感","product_picture":"public/imgs/accessory/protectingMen-Mi-CC9.png","product_price":19.00,"product_selling_price":19.00,"product_num":20,"product_sales":0},{"product_id":22,"product_name":"小米CC9e 标准高透贴膜","category_id":6,"product_title":"高清透亮,耐磨性强","product_intro":"耐磨性强,防护更出众 / 疏油疏水,有效抗水抗脏污 / 高清透亮,保留了原生屏幕的亮丽颜色和清晰度 / 操作灵敏,智能吸附 / 进口高端PET材质,裸机般手感","product_picture":"public/imgs/accessory/protectingMen-Mi-CC9e.png","product_price":19.00,"product_selling_price":19.00,"product_num":20,"product_sales":0}],"pageSize":3,"pageCount":2,"filterCount":0}
开始你的任务吧,祝你成功!
ProductDao.java
package com.lxc.dao;
import com.lxc.entity.Category;
import com.lxc.entity.Product;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ProductDao {
/*********************************Begin*********************************/
//对上线商品中的商品名,商品标题,商品描述进行关键字对比
//对上线商品中的商品名,商品标题,商品描述进行关键字对比
@Select("select * from product where status=1 and product_name like '%${search}%' or product_title like '%${search}%' or product_intro like '%${search}%' limit #{filterCount} , #{pageSize}")
List<Product> getProductBySearch(String search,int filterCount,int pageSize);
//查询符合条件的商品的数量
@Select("select count(1) from product where status=1 and product_name like '%${search}%' or product_title like '%${search}%' or product_intro like '%${search}%'")
int getProductCountBySearch(String search);
/*********************************End*********************************/
}
ProductService.java
package com.lxc.service;
import com.lxc.entity.Page;
import com.lxc.entity.Product;
import org.springframework.stereotype.Component;
@Component
public interface ProductService {
/*********************************Begin*********************************/
// 根据关键字搜索商品
Page<Product> getProductBySearch(String search, int filterCount, int pageSize);
/*********************************End*********************************/
}
ProductServiceImpl.java
package com.lxc.service.impl;
import com.lxc.dao.ProductDao;
import com.lxc.entity.Page;
import com.lxc.entity.Product;
import com.lxc.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service("productService")
public class ProductServiceImpl implements ProductService {
@Autowired
Page<Product> page;
@Autowired
private ProductDao productDao;
@Override
public Page<Product> getProductBySearch(String search,int currentPage,int pageSize) {
/*********************************Begin*********************************/
//数据总条数存入page对象
page.setCount(productDao.getProductCountBySearch(search));
//设置当前页数
page.setCurrPage(currentPage);
//设置每页条数
page.setPageSize(pageSize);
//设置过滤条数过滤前面页面数据
page.setFilterCount((page.getCurrPage()-1)*page.getPageSize());
//设置总页数,总页数+每页条数-1再运算可使总页数向上取整
page.setPageCount((page.getCount()+page.getPageSize()-1)/page.getPageSize());
//设置下一页
page.setNextPage(page.getCurrPage()==page.getPageCount()?page.getCurrPage():page.getCurrPage()+1);
//设置上一页
page.setPrePage(page.getCurrPage()==1?page.getCurrPage():page.getCurrPage()-1);
page.setList(productDao.getProductBySearch(search,page.getFilterCount(),page.getPageSize()));
return page;
/*********************************End*********************************/
}
}
ProductController.java
package com.lxc.controller;
import com.lxc.entity.Page;
import com.lxc.service.ProductService;
import com.lxc.entity.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping(value = "/product")
public class ProductController {
@Autowired
Page<Product> page;
@Autowired
private ProductService productService;
/**
* 搜索框查询
* @param paramMap
* @return
*/
@RequestMapping(value = "/getProductBySearch")
public Page<Product> getProductBySearch(@RequestBody Map<String,Object> paramMap){
/*********************************Begin*********************************/
String search = String.valueOf(paramMap.get("search"));
int currentPage =Integer.parseInt (String.valueOf(paramMap.get("currentPage")));
int pageSize = Integer.parseInt (String.valueOf(paramMap.get("pageSize")));
//根据关键字搜索所有商品
return productService.getProductBySearch(search,currentPage,pageSize);
/*********************************End*********************************/
}
}
Product.java
package com.lxc.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class Product implements Serializable {
private int product_id;
private String product_name;
private int category_id;
private String product_title;
private String product_intro;
private String product_picture;
private BigDecimal product_price; //原价
private BigDecimal product_selling_price; //售价
private int product_num;
private int product_sales;
}
第4关:根据 id 查询商品信息
任务描述
本关任务:实现查询商品详细信息功能。
相关知识
为了完成本关任务,你需要掌握:
- 查询商品详细信息。
- 功能实现。
查询商品详细信息
我们在购物商城看到喜欢的商品时通常会点进去查看商品的具体信息,如下有一些商品:
当我们觉得 1299 的手机还不错时就可以点进去查看具体信息:
这个过程其实就是通过商品表的一个唯一字段去通过服务器查询数据库某一具体商品信息的过程。即点击该商品时获取该商品 id ,请求服务器通过该 id 查询数据库并返回商品信息的过程。
功能实现
以下通过 Mybatis 的注解式 sql 实现:
- dao 层接收参数查询数据库:
@Repository
public interface ProductDao {
//根据商品id product_id 查询商品表 product 的具体信息
@Select("select * from product where product_id=#{product_id}")
Product getProductByID(int product_id);
}
- service 层定义接口并写好逻辑代码:
public interface ProductService {
//定义接口
Product getProductByID(int product_id);
}
public Product getProductByID(int product_id) {
//从 redis 中查询
Map<Object, Object> productMap = redisTemplate.opsForHash().entries("product");
if(productMap.isEmpty()){ //redis无map
//通过商品id从数据库查询该商品
Product product = productDao.getProductByID(product_id);
//商品存入 map
productMap.put(product_id+"",product);
//map 存入 redis
redisTemplate.opsForHash().putAll("product",productMap);
}else if(productMap.get(product_id)==null){ //redis无该商品
//商品存入 map
productMap.put(product_id+"",productDao.getProductByID(product_id));
//map 存入 redis
redisTemplate.opsForHash().putAll("product",productMap);
}
//返回商品 map 中的该商品id的具体信息
return (Product) productMap.get(product_id+"");
}
- controller 层:
@RequestMapping(value = "/getDetails")
public Map getDetails(@RequestBody Map<String,Integer> paramMap){
//接收 参数
int productID = paramMap.get("productID");
//调用 service 接口的查询方法
Product product = productService.getProductByID(productID);
//返回结果集
HashMap<String, Object> map = new HashMap<>();
map.put("Product",new ArrayList<Product>(){{this.add(product);}});
return map;
}
- 数据库如下:
字段名称 类型 备注 product_id
int(11) NOT NULL AUTO_INCREMENT '商品id' product_name
char(100) NOT NULL '商品名' category_id
int(11) NOT NULL '类型id' product_title
char(30) NOT NULL '商品标题' product_intro
text NOT NULL '商品描述' product_picture
char(200) DEFAULT NULL '商品图片' product_price
decimal(10,2) NOT NULL '商品价格' product_selling_price
decimal(10,2) NOT NULL '商品售价' product_num
int(11) NOT NULL '商品存量' product_sales
int(11) NOT NULL '商品销售数量' status
int(11) DEFAULT NULL '商品状态'
编程要求
在 productDao.java、productService.java、productServiceImpl.java、productController.java 中根据提示补充代码。
测试说明
平台会对你编写的代码进行测试:发送请求获取结果集,判断结果集是否正确。 预期输入:
{
"productID":"3"
}
预期输出:
{"Product":[{"product_id":3,"product_name":"小米CC9 Pro","category_id":1,"product_title":"1亿像素,五摄四闪","product_intro":"1亿像素主摄 / 全场景五摄像头 / 四闪光灯 / 3200万自拍 / 10 倍混合光学变焦,50倍数字变焦 / 5260mAh ⼤电量 / 标配 30W疾速快充 / ⼩米⾸款超薄屏下指纹 / 德国莱茵低蓝光认证 / 多功能NFC / 红外万能遥控 / 1216超线性扬声器","product_picture":"public/imgs/phone/Mi-CC9.png","product_price":2799.00,"product_selling_price":2599.00,"product_num":20,"product_sales":0}]}
开始你的任务吧,祝你成功!
productDao.java
package com.lxc.dao;
import com.lxc.entity.Product;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductDao {
//根据商品 id 查询商品信息
/*********************************Begin*********************************/
@Select("select * from product where product_id=#{product_id}")
Product getProductByID(int product_id);
/*********************************End*********************************/
}
productService.java
package com.lxc.service;
import com.lxc.entity.Page;
import com.lxc.entity.Product;
import org.springframework.stereotype.Component;
@Component
public interface ProductService {
//定义 service 接口
/*********************************Begin*********************************/
Product getProductByID(int product_id);
/*********************************End*********************************/
}
productServiceImpl.java
package com.lxc.service.impl;
import com.lxc.dao.ProductDao;
import com.lxc.entity.Page;
import com.lxc.entity.Product;
import com.lxc.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service("productService")
public class ProductServiceImpl implements ProductService {
@Autowired
Page<Product> page;
@Autowired
private ProductDao productDao;
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@Override
public Product getProductByID(int product_id) {
//从 redis 中查询
Map<Object, Object> productMap = redisTemplate.opsForHash().entries("product");
if(productMap.isEmpty()){ //redis无map
//通过商品id从数据库查询该商品
Product product = productDao.getProductByID(product_id);
//商品存入 map
productMap.put(product_id+"",product);
//map 存入 redis
redisTemplate.opsForHash().putAll("product",productMap);
}else if(productMap.get(product_id)==null){ //redis无该商品
//商品存入 map
productMap.put(product_id+"",productDao.getProductByID(product_id));
//map 存入 redis
redisTemplate.opsForHash().putAll("product",productMap);
}
//返回商品 map 中的该商品id的具体信息
return (Product) productMap.get(product_id+"");
}
}
productController.java
package com.lxc.controller;
import com.lxc.entity.Page;
import com.lxc.service.ProductService;
import com.lxc.entity.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping(value = "/product")
public class ProductController {
@Autowired
Page<Product> page;
@Autowired
private ProductService productService;
/**
* 根据商品 id 查询商品具体信息
* @param paramMap
* @return
*/
@RequestMapping(value = "/getDetails")
public Map getDetails(@RequestBody Map<String,Integer> paramMap){
//接收 参数
int productID = paramMap.get("productID");
//调用 service 接口的查询方法
Product product = productService.getProductByID(productID);
//返回结果集
HashMap<String, Object> map = new HashMap<>();
map.put("Product",new ArrayList<Product>(){{this.add(product);}});
return map;
}
}
Product.java
package com.lxc.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class Product implements Serializable {
private int product_id;
private String product_name;
private int category_id;
private String product_title;
private String product_intro;
private String product_picture;
private BigDecimal product_price; //原价
private BigDecimal product_selling_price; //售价
private int product_num;
private int product_sales;
}
加油哦,同学们!