千峰商城-springboot项目搭建-59-分类列表数据库实现连接查询
一、首页-分类列表 实现流程分析:
1.方案一:一次查询三级分类
优点:只需要一次查询,根据一级分类显示二级分类时响应速度较快。
缺点:数据库查询效率较低,页面首次加载的速度也相对较慢。
2.方案二:先只查询一级分类,用户点击/鼠标移动到一级分类,动态加载二级分类。
优点:数据库查询效率提高,页面首次加载速度提高。
缺点:需要多次连接数据库查询。
二、数据库操作实现
1.数据表结构:
Field Type Collation Null Key Default Extra Privileges Comment
----------------- ----------- --------------- ------ ------ ------- -------------- ------------------------------- ------------------------------------------------------------------------------------------------
category_id int(11) (NULL) NO PRI (NULL) auto_increment select,insert,update,references 主键 分类id主键
category_name varchar(32) utf8_general_ci NO (NULL) select,insert,update,references 分类名称 分类名称
category_level int(11) (NULL) NO (NULL) select,insert,update,references 分类层级 分类得类型,
1:一级大分类
2:二级分类
3:三级小分类
parent_id int(11) (NULL) NO (NULL) select,insert,update,references 父层级id 父id 上一级依赖的id,1级分类则为0,二级三级分别依赖上一级
category_icon varchar(64) utf8_general_ci YES (NULL) select,insert,update,references 图标 logo
category_slogan varchar(64) utf8_general_ci YES (NULL) select,insert,update,references 口号
category_pic varchar(64) utf8_general_ci YES (NULL) select,insert,update,references 分类图
category_bg_color varchar(32) utf8_general_ci YES (NULL) select,insert,update,references 背景颜色
CREATE TABLE `category` ( `category_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键 分类id主键', `category_name` varchar(32) NOT NULL COMMENT '分类名称 分类名称', `category_level` int(11) NOT NULL COMMENT '分类层级 分类得类型,\n1:一级大分类\n2:二级分类\n3:三级小分类', `parent_id` int(11) NOT NULL COMMENT '父层级id 父id 上一级依赖的id,1级分类则为0,二级三级分别依赖上一级', `category_icon` varchar(64) DEFAULT NULL COMMENT '图标 logo', `category_slogan` varchar(64) DEFAULT NULL COMMENT '口号', `category_pic` varchar(64) DEFAULT NULL COMMENT '分类图', `category_bg_color` varchar(32) DEFAULT NULL COMMENT '背景颜色', PRIMARY KEY (`category_id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=52 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='商品分类'
2.添加测试数据。
3.编写接口实现所需的SQL:
连接查询:
#查询三级分类 SELECT c1.category_id 'category_id1', c1.category_name 'category_name1', c1.category_level 'category_level1', c1.parent_id 'parent_id1', c1.category_icon 'category_icon1', c1.category_slogan 'category_slogan1', c1.category_pic 'category_pic1', c1.category_bg_color 'category_bg_color1', c2.category_id 'category_id2', c2.category_name 'category_name2', c2.category_level 'category_level2', c2.parent_id 'parent_id2', c3.category_id 'category_id3', c3.category_name 'category_name3', c3.category_level 'category_level3', c3.parent_id 'parent_id3'FROM category c1 INNER JOIN category c2 ON c2.parent_id=c1.category_id LEFT JOIN category c3 ON c3.parent_id=c2.category_id WHERE c1.category_level=1
子查询:
#子查询(根据父级分类的id查询类别信息) SELECT * FROM category WHERE parent_id = 3
三、DAO定义接口
1.创建用于封装查询的类别信息CategoryVO:
在beans子工程的entity包新建一个CategoryVO用于封装查询到的类别信息,相对于Category来说,新增了一个属性List<CatetoryVO> catetories。
package com.qfedu.fmmall.vo; import javax.persistence.Column; import javax.persistence.Id; import java.util.List; public class CatetoryVO { /** * 主键 分类id主键 */ @Id @Column(name = "category_id") private Integer categoryId; /** * 分类名称 分类名称 */ @Column(name = "category_name") private String categoryName; /** * 分类层级 分类得类型, 1:一级大分类 2:二级分类 3:三级小分类 */ @Column(name = "category_level") private Integer categoryLevel; /** * 父层级id 父id 上一级依赖的id,1级分类则为0,二级三级分别依赖上一级 */ @Column(name = "parent_id") private Integer parentId; /** * 图标 logo */ @Column(name = "category_icon") private String categoryIcon; /** * 口号 */ @Column(name = "category_slogan") private String categorySlogan; /** * 分类图 */ @Column(name = "category_pic") private String categoryPic; /** * 背景颜色 */ @Column(name = "category_bg_color") private String categoryBgColor; //用于存放当前分类的子分类 private List<CategoryVO> categories; public List<CategoryVO> getCategories() { return categories; } public void setCategories(List<CategoryVO> categories) { this.categories = categories; } /** * 获取主键 分类id主键 * * @return category_id - 主键 分类id主键 */ public Integer getCategoryId() { return categoryId; } /** * 设置主键 分类id主键 * * @param categoryId 主键 分类id主键 */ public void setCategoryId(Integer categoryId) { this.categoryId = categoryId; } /** * 获取分类名称 分类名称 * * @return category_name - 分类名称 分类名称 */ public String getCategoryName() { return categoryName; } /** * 设置分类名称 分类名称 * * @param categoryName 分类名称 分类名称 */ public void setCategoryName(String categoryName) { this.categoryName = categoryName; } /** * 获取分类层级 分类得类型, 1:一级大分类 2:二级分类 3:三级小分类 * * @return category_level - 分类层级 分类得类型, 1:一级大分类 2:二级分类 3:三级小分类 */ public Integer getCategoryLevel() { return categoryLevel; } /** * 设置分类层级 分类得类型, 1:一级大分类 2:二级分类 3:三级小分类 * * @param categoryLevel 分类层级 分类得类型, 1:一级大分类 2:二级分类 3:三级小分类 */ public void setCategoryLevel(Integer categoryLevel) { this.categoryLevel = categoryLevel; } /** * 获取父层级id 父id 上一级依赖的id,1级分类则为0,二级三级分别依赖上一级 * * @return parent_id - 父层级id 父id 上一级依赖的id,1级分类则为0,二级三级分别依赖上一级 */ public Integer getParentId() { return parentId; } /** * 设置父层级id 父id 上一级依赖的id,1级分类则为0,二级三级分别依赖上一级 * * @param parentId 父层级id 父id 上一级依赖的id,1级分类则为0,二级三级分别依赖上一级 */ public void setParentId(Integer parentId) { this.parentId = parentId; } /** * 获取图标 logo * * @return category_icon - 图标 logo */ public String getCategoryIcon() { return categoryIcon; } /** * 设置图标 logo * * @param categoryIcon 图标 logo */ public void setCategoryIcon(String categoryIcon) { this.categoryIcon = categoryIcon; } /** * 获取口号 * * @return category_slogan - 口号 */ public String getCategorySlogan() { return categorySlogan; } /** * 设置口号 * * @param categorySlogan 口号 */ public void setCategorySlogan(String categorySlogan) { this.categorySlogan = categorySlogan; } /** * 获取分类图 * * @return category_pic - 分类图 */ public String getCategoryPic() { return categoryPic; } /** * 设置分类图 * * @param categoryPic 分类图 */ public void setCategoryPic(String categoryPic) { this.categoryPic = categoryPic; } /** * 获取背景颜色 * * @return category_bg_color - 背景颜色 */ public String getCategoryBgColor() { return categoryBgColor; } /** * 设置背景颜色 * * @param categoryBgColor 背景颜色 */ public void setCategoryBgColor(String categoryBgColor) { this.categoryBgColor = categoryBgColor; } }
2.在CategoryMapper定义如下方法:
public interface CategoryMapper extends GeneralDAO<Category> {
//1.使用连接查询实现分类查询 public List<CategoryVO> selectAllCategories(); }
3.映射配置mapper.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.qfedu.fmmall.dao.CategoryMapper"> <resultMap id="BaseResultMap" type="com.qfedu.fmmall.entity.Category"> <!-- WARNING - @mbg.generated --> <id column="category_id" jdbcType="INTEGER" property="categoryId" /> <result column="category_name" jdbcType="VARCHAR" property="categoryName" /> <result column="category_level" jdbcType="INTEGER" property="categoryLevel" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> <result column="category_icon" jdbcType="VARCHAR" property="categoryIcon" /> <result column="category_slogan" jdbcType="VARCHAR" property="categorySlogan" /> <result column="category_pic" jdbcType="VARCHAR" property="categoryPic" /> <result column="category_bg_color" jdbcType="VARCHAR" property="categoryBgColor" /> </resultMap> <resultMap id="categoryVOMap" type="com.qfedu.fmmall.entity.CategoryVO"> <!-- WARNING - @mbg.generated --> <id column="category_id1" jdbcType="INTEGER" property="categoryId" /> <result column="category_name1" jdbcType="VARCHAR" property="categoryName" /> <result column="category_level1" jdbcType="INTEGER" property="categoryLevel" /> <result column="parent_id1" jdbcType="INTEGER" property="parentId" /> <result column="category_icon1" jdbcType="VARCHAR" property="categoryIcon" /> <result column="category_slogan1" jdbcType="VARCHAR" property="categorySlogan" /> <result column="category_pic1" jdbcType="VARCHAR" property="categoryPic" /> <result column="category_bg_color1" jdbcType="VARCHAR" property="categoryBgColor" /> <collection property="categories" ofType="com.qfedu.fmmall.entity.CategoryVO" javaType="list"> <id column="category_id2" jdbcType="INTEGER" property="categoryId" /> <result column="category_name2" jdbcType="VARCHAR" property="categoryName" /> <result column="category_level2" jdbcType="INTEGER" property="categoryLevel" /> <result column="parent_id2" jdbcType="INTEGER" property="parentId" /> <collection property="categories" ofType="com.qfedu.fmmall.entity.CategoryVO" javaType="list"> <id column="category_id3" jdbcType="INTEGER" property="categoryId" /> <result column="category_name3" jdbcType="VARCHAR" property="categoryName" /> <result column="category_level3" jdbcType="INTEGER" property="categoryLevel" /> <result column="parent_id3" jdbcType="INTEGER" property="parentId" /> </collection> </collection> </resultMap> <select id="selectAllCategories" resultMap="categoryVOMap"> SELECT c1.category_id 'category_id1', c1.category_name 'category_name1', c1.category_level 'category_level1', c1.parent_id 'parent_id1', c1.category_icon 'category_icon1', c1.category_slogan 'category_slogan1', c1.category_pic 'category_pic1', c1.category_bg_color 'category_bg_color1', c2.category_id 'category_id2', c2.category_name 'category_name2', c2.category_level 'category_level2', c2.parent_id 'parent_id2', c3.category_id 'category_id3', c3.category_name 'category_name3', c3.category_level 'category_level3', c3.parent_id 'parent_id3' FROM category c1 INNER JOIN category c2 ON c2.parent_id=c1.category_id LEFT JOIN category c3 ON c3.parent_id=c2.category_id WHERE c1.category_level=1 </select> </mapper>
4.测试:
package com.qfedu.fmmall; import com.qfedu.fmmall.dao.CategoryMapper; import com.qfedu.fmmall.entity.CategoryVO; //import org.junit.jupiter.api.Test; import org.junit.Test; import org.junit.runner.RunWith; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest(classes = ApiApplication.class) public class ApiApplicationTests { @Autowired private CategoryMapper categoryMapper; @Test public void contextLoads() { List<CategoryVO> categoryVOS = categoryMapper.selectAllCategories(); for (CategoryVO c1:categoryVOS){ System.out.println(c1); for (CategoryVO c2: c1.getCategories()){ System.out.println("\t"+c2); for (CategoryVO c3: c2.getCategories()){ System.out.println("\t\t"+c3); } } } } }
5.方案二:子查询:
@Repository public interface CategoryMapper extends GeneralDAO<Category> { //1.使用连接查询实现分类查询 public List<CategoryVO> selectAllCategories(); //2.子查询,就是根据parentId查询子分类 public List<CategoryVO> selectAllCategories2(int parentId); }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.qfedu.fmmall.dao.CategoryMapper"> <resultMap id="BaseResultMap" type="com.qfedu.fmmall.entity.Category"> <!-- WARNING - @mbg.generated --> <id column="category_id" jdbcType="INTEGER" property="categoryId" /> <result column="category_name" jdbcType="VARCHAR" property="categoryName" /> <result column="category_level" jdbcType="INTEGER" property="categoryLevel" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> <result column="category_icon" jdbcType="VARCHAR" property="categoryIcon" /> <result column="category_slogan" jdbcType="VARCHAR" property="categorySlogan" /> <result column="category_pic" jdbcType="VARCHAR" property="categoryPic" /> <result column="category_bg_color" jdbcType="VARCHAR" property="categoryBgColor" /> </resultMap> <resultMap id="categoryVOMap" type="com.qfedu.fmmall.entity.CategoryVO"> <!-- WARNING - @mbg.generated --> <id column="category_id1" jdbcType="INTEGER" property="categoryId" /> <result column="category_name1" jdbcType="VARCHAR" property="categoryName" /> <result column="category_level1" jdbcType="INTEGER" property="categoryLevel" /> <result column="parent_id1" jdbcType="INTEGER" property="parentId" /> <result column="category_icon1" jdbcType="VARCHAR" property="categoryIcon" /> <result column="category_slogan1" jdbcType="VARCHAR" property="categorySlogan" /> <result column="category_pic1" jdbcType="VARCHAR" property="categoryPic" /> <result column="category_bg_color1" jdbcType="VARCHAR" property="categoryBgColor" /> <collection property="categories" ofType="com.qfedu.fmmall.entity.CategoryVO" javaType="list"> <id column="category_id2" jdbcType="INTEGER" property="categoryId" /> <result column="category_name2" jdbcType="VARCHAR" property="categoryName" /> <result column="category_level2" jdbcType="INTEGER" property="categoryLevel" /> <result column="parent_id2" jdbcType="INTEGER" property="parentId" /> <collection property="categories" ofType="com.qfedu.fmmall.entity.CategoryVO" javaType="list"> <id column="category_id3" jdbcType="INTEGER" property="categoryId" /> <result column="category_name3" jdbcType="VARCHAR" property="categoryName" /> <result column="category_level3" jdbcType="INTEGER" property="categoryLevel" /> <result column="parent_id3" jdbcType="INTEGER" property="parentId" /> </collection> </collection> </resultMap> <select id="selectAllCategories" resultMap="categoryVOMap"> SELECT c1.category_id 'category_id1', c1.category_name 'category_name1', c1.category_level 'category_level1', c1.parent_id 'parent_id1', c1.category_icon 'category_icon1', c1.category_slogan 'category_slogan1', c1.category_pic 'category_pic1', c1.category_bg_color 'category_bg_color1', c2.category_id 'category_id2', c2.category_name 'category_name2', c2.category_level 'category_level2', c2.parent_id 'parent_id2', c3.category_id 'category_id3', c3.category_name 'category_name3', c3.category_level 'category_level3', c3.parent_id 'parent_id3' FROM category c1 INNER JOIN category c2 ON c2.parent_id=c1.category_id LEFT JOIN category c3 ON c3.parent_id=c2.category_id WHERE c1.category_level=1 </select> <resultMap id="categoryVOMap2" type="com.qfedu.fmmall.entity.CategoryVO"> <!-- WARNING - @mbg.generated --> <id column="category_id" jdbcType="INTEGER" property="categoryId" /> <result column="category_name" jdbcType="VARCHAR" property="categoryName" /> <result column="category_level" jdbcType="INTEGER" property="categoryLevel" /> <result column="parent_id" jdbcType="INTEGER" property="parentId" /> <result column="category_icon" jdbcType="VARCHAR" property="categoryIcon" /> <result column="category_slogan" jdbcType="VARCHAR" property="categorySlogan" /> <result column="category_pic" jdbcType="VARCHAR" property="categoryPic" /> <result column="category_bg_color" jdbcType="VARCHAR" property="categoryBgColor" /> <collection property="categories" column="category_id" select="com.qfedu.fmmall.dao.CategoryMapper.selectAllCategories2"/> </resultMap> <!-- 根据父级分类的id查询子级分类--> <select id="selectAllCategories2" resultMap="categoryVOMap2"> select category_id, category_name, category_level, parent_id, category_icon, category_slogan, category_pic, category_bg_color from category where parent_id=#{parentId} </select> </mapper>
package com.qfedu.fmmall; import com.qfedu.fmmall.dao.CategoryMapper; import com.qfedu.fmmall.entity.CategoryVO; //import org.junit.jupiter.api.Test; import org.junit.Test; import org.junit.runner.RunWith; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest(classes = ApiApplication.class) public class ApiApplicationTests { @Autowired private CategoryMapper categoryMapper; @Test public void contextLoads() { List<CategoryVO> categoryVOS = categoryMapper.selectAllCategories2(0); for (CategoryVO c1:categoryVOS){ System.out.println(c1); for (CategoryVO c2: c1.getCategories()){ System.out.println("\t"+c2); for (CategoryVO c3: c2.getCategories()){ System.out.println("\t\t"+c3); } } } } }