当前位置:   article > 正文

MyBatis-plus实现三级联动查询、涉及分页和模糊查询的联表查询处理_mybatisplus 级联查询

mybatisplus 级联查询

一、三级联动(以省份-城市-考场为例)

1)表设计

省份和城市存在同一张表,parentId为0代表省,parentId不为零代表对应省份下的城市。

  1. package com.example.jiakao.pojo.entity;
  2. import com.baomidou.mybatisplus.annotation.IdType;
  3. import com.baomidou.mybatisplus.annotation.TableId;
  4. import com.baomidou.mybatisplus.annotation.TableName;
  5. import lombok.Data;
  6. import javax.persistence.*;
  7. @Entity
  8. @Data
  9. @TableName("plate_region")
  10. @Table(name="plate_region")
  11. public class PlateRegionPo {
  12. @Id
  13. @TableId(type = IdType.AUTO)
  14. @GeneratedValue(strategy = GenerationType.IDENTITY)
  15. @Column( columnDefinition = "int4" )
  16. private Integer id;
  17. @Column( columnDefinition = "varchar(64)" )
  18. private String name;
  19. @Column( columnDefinition = "varchar(64)" )
  20. private String plate;
  21. @Column( columnDefinition = "int4 default 0 " )
  22. private Integer parentId;
  23. }

 考场表,parentId对应城市id

  1. import com.baomidou.mybatisplus.annotation.IdType;
  2. import com.baomidou.mybatisplus.annotation.TableId;
  3. import com.baomidou.mybatisplus.annotation.TableName;
  4. import lombok.Data;
  5. import javax.persistence.*;
  6. @Entity
  7. @Data
  8. @TableName("exam_place")
  9. @Table(name="exam_place")
  10. public class ExamPlacePo {
  11. @Id
  12. @TableId(type = IdType.AUTO)
  13. @GeneratedValue(strategy = GenerationType.IDENTITY)
  14. @Column( columnDefinition = "bigint" )
  15. private Long id;
  16. @Column( columnDefinition = "varchar(64)" )
  17. private String name;
  18. @Column( columnDefinition = "int4" )
  19. private Integer parentId;
  20. }

2)定义返回类型vo

  1. package com.example.jiakao.pojo.vo.list;
  2. import lombok.Data;
  3. import java.util.List;
  4. @Data
  5. public class ProvinceVo {
  6. private Long id;
  7. private String name;
  8. private String plate;
  9. private List<CityVo> children;
  10. }
  1. package com.example.jiakao.pojo.vo.list;
  2. import lombok.Data;
  3. import java.util.List;
  4. @Data
  5. public class CityVo {
  6. private Long id;
  7. private String name;
  8. private String plate;
  9. private List<ExamPlaceVo> children;
  10. }
  1. package com.example.jiakao.pojo.vo.list;
  2. import lombok.Data;
  3. @Data
  4. public class ExamPlaceVo {
  5. private Long id;
  6. private String name;
  7. }

3)mapper.xml查询语句

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.example.jiakao.mapper.ExamPlacePoMapper">
  4. <resultMap id="selectRegionExamPlaces" type="com.example.jiakao.pojo.vo.list.ProvinceVo">
  5. <id column="id" property="id"></id>
  6. <result column="name" property="name"></result>
  7. <result column="plate" property="plate"></result>
  8. <collection property="children" ofType="com.example.jiakao.pojo.vo.list.CityVo">
  9. <id column="city_id" property="id"></id>
  10. <result column="city_name" property="name"></result>
  11. <result column="city_plate" property="plate"></result>
  12. <collection property="children" ofType="com.example.jiakao.pojo.vo.list.ExamPlaceVo">
  13. <id column="exam_id" property="id"></id>
  14. <result column="exam_name" property="name"></result>
  15. </collection>
  16. </collection>
  17. </resultMap>
  18. <select id="listRegionExamPlaces" resultMap="selectRegionExamPlaces">
  19. select
  20. p.id,
  21. p.name,
  22. p.plate,
  23. c.id city_id,
  24. c.name city_name,
  25. c.plate city_plate,
  26. e.id exam_id,
  27. e.name exam_name
  28. from plate_region p
  29. join plate_region c on c.parent_id = p.id
  30. join exam_place e on e.parent_id = c.id
  31. where p.parent_id = 0
  32. </select>
  33. </mapper>

4)查询结果

  1. {
  2. "code": 200,
  3. "message": "成功",
  4. "data": [
  5. {
  6. "id": 2,
  7. "name": "湖北",
  8. "plate": "鄂",
  9. "children": [
  10. {
  11. "id": 3,
  12. "name": "武汉",
  13. "plate": "A",
  14. "children": [
  15. {
  16. "id": 1,
  17. "name": "hfgg"
  18. },
  19. {
  20. "id": 5,
  21. "name": "hgi"
  22. }
  23. ]
  24. }
  25. ]
  26. },
  27. {
  28. "id": 1,
  29. "name": "广东",
  30. "plate": "粤",
  31. "children": [
  32. {
  33. "id": 7,
  34. "name": "深圳",
  35. "plate": "B",
  36. "children": [
  37. {
  38. "id": 6,
  39. "name": "hgiG"
  40. }
  41. ]
  42. },
  43. {
  44. "id": 8,
  45. "name": "广州",
  46. "plate": "A",
  47. "children": [
  48. {
  49. "id": 7,
  50. "name": "hgU"
  51. },
  52. {
  53. "id": 8,
  54. "name": "hgUU"
  55. }
  56. ]
  57. }
  58. ]
  59. }
  60. ]
  61. }

5)注意点

        join、left join、right join三者的区别简单概括:join取两张表的交集,只保留有交集的条目;left join以join之前的表为主表,无论有没有交集,主表条目都存在;right join以join之后的表为主表。

二、关于带有模糊查询以及分页的联表查询处理(以考场-考试科目为例)

1)vo定义,用于保存数据时传参,与po对象字段对应,只忽略po对象中不需要用户操作的字段。

  1. package com.example.jiakao.pojo.vo.req.save;
  2. import io.swagger.annotations.ApiModel;
  3. import io.swagger.annotations.ApiModelProperty;
  4. import lombok.Data;
  5. import javax.validation.constraints.NotBlank;
  6. import javax.validation.constraints.NotNull;
  7. @Data
  8. @ApiModel("保存考场信息的参数")
  9. public class ExamPlaceReqVo {
  10. @ApiModelProperty(value = "考场id")
  11. private Long id;
  12. @ApiModelProperty(value = "考场名称", required = true)
  13. @NotBlank(message = "名称不能为空")
  14. private String name;
  15. @ApiModelProperty(value = "考场所属城市id", required = true)
  16. @NotNull(message = "所属城市不能为空")
  17. private Integer cityId;
  18. @ApiModelProperty(value = "考场所属省份id", required = true)
  19. @NotNull(message = "所属省份不能为空")
  20. private Integer provinceId;
  21. }
  1. package com.example.jiakao.pojo.vo.req.save;
  2. import com.example.jiakao.common.validator.BoolNumber;
  3. import io.swagger.annotations.ApiModel;
  4. import io.swagger.annotations.ApiModelProperty;
  5. import lombok.Data;
  6. import javax.validation.constraints.Min;
  7. import javax.validation.constraints.NotBlank;
  8. import javax.validation.constraints.NotNull;
  9. @Data
  10. @ApiModel("保存课程信息")
  11. public class ExamCourseReqVo {
  12. @ApiModelProperty("课程id")
  13. private Long id;
  14. @ApiModelProperty(value = "课程名称", required = true)
  15. @NotBlank(message = "课程名不能为空")
  16. private String name;
  17. @ApiModelProperty(value = "课程类型",required = true)
  18. @NotNull(message = "课程类型不能为空")
  19. @BoolNumber(message = "课程类型值为0或1")
  20. private Short type;
  21. @ApiModelProperty(value = "课程价格",required = true)
  22. @NotNull(message = "课程价格不能为空")
  23. @Min(value = 0, message = "价格不能为负数")
  24. private Double price;
  25. @ApiModelProperty(value = "课程所属考场",required = true)
  26. @NotNull(message = "所属考场不能为空")
  27. private Long examPlaceId;
  28. }

 返回列表的vo定义,用于构建返回结果实体。

  1. package com.example.jiakao.pojo.vo.list;
  2. import io.swagger.annotations.ApiModel;
  3. import io.swagger.annotations.ApiModelProperty;
  4. import lombok.Data;
  5. @Data
  6. @ApiModel("课程信息返回值")
  7. public class ExamCourseVo {
  8. @ApiModelProperty("课程id")
  9. private Long id;
  10. @ApiModelProperty(value = "课程名称")
  11. private String name;
  12. @ApiModelProperty(value = "课程类型")
  13. private Short type;
  14. @ApiModelProperty(value = "课程价格")
  15. private Double price;
  16. @ApiModelProperty(value = "课程所属考场")
  17. private Long examPlaceId;
  18. @ApiModelProperty(value = "考场所属省份")
  19. private Integer provinceId;
  20. @ApiModelProperty(value = "考场所属城市")
  21. private Integer cityId;
  22. }

2)Service和Mapper

        因为我们使用的两张表中都有name字段,因此我们在构造QueryWrapper时需要明确标出时哪一张表的name字段,因此这里使用QueryWrapper而不能使用LambdaQueryWrapper。

  1. package com.example.jiakao.service;
  2. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  3. import com.example.jiakao.common.enhance.MpPage;
  4. import com.example.jiakao.common.enhance.MpQueryWrapper;
  5. import com.example.jiakao.mapper.ExamCourseMapper;
  6. import com.example.jiakao.pojo.entity.ExamCoursePo;
  7. import com.example.jiakao.pojo.vo.json.PageVo;
  8. import com.example.jiakao.pojo.vo.list.ExamCourseVo;
  9. import com.example.jiakao.pojo.vo.req.query.KeyWordReqVo;
  10. import org.springframework.stereotype.Service;
  11. @Service
  12. public class ExamCourseService extends ServiceImpl<ExamCourseMapper, ExamCoursePo> {
  13. public PageVo<ExamCourseVo> listCoursesPage(KeyWordReqVo query) {
  14. MpPage<ExamCourseVo> mpPage= new MpPage<>(query);
  15. MpQueryWrapper<ExamCourseVo> wrapper = new MpQueryWrapper<>();
  16. wrapper.likes(query.getKeyword(),"c.name");
  17. baseMapper.selectCourses(mpPage,wrapper);
  18. return mpPage.buildVo();
  19. }
  20. } }
  21. }
  1. package com.example.jiakao.mapper;
  2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  3. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4. import com.baomidou.mybatisplus.core.toolkit.Constants;
  5. import com.example.jiakao.common.enhance.MpPage;
  6. import com.example.jiakao.pojo.entity.ExamCoursePo;
  7. import com.example.jiakao.pojo.vo.list.ExamCourseVo;
  8. import org.apache.ibatis.annotations.Param;
  9. //官方推荐前缀Constants.WRAPPER => ew
  10. public interface ExamCourseMapper extends BaseMapper<ExamCoursePo> {
  11. public MpPage<ExamCourseVo> selectCourses(MpPage<ExamCourseVo> page,
  12. @Param(Constants.WRAPPER) QueryWrapper wrapper);
  13. }

        当我们在Mapper的方法中传入和返回的类型都是IPage接口的实现时,Mybatis-plus会自动帮我们分页,也就是在查询语句后拼接limit。但是查询条件不会帮我们自动实现,需要我们手动调用QueryWrapper类型的customSqlSegment获取SQL语句然后拼接到xml中。注意使用${}进行拼接,而不是#{},$是直接替换,而#会进行预编译。

        当然我们也可以在有需要时对除BaseMapper泛型的实体以外的自定义实体构造LambdaQueryWrapper,此时我们需要增加afterPropertiesSet配置。

  1. public class MyBatisPlusConfig implements InitializingBean {
  2. @Bean
  3. public MybatisPlusInterceptor mybatisPlusInterceptor() {
  4. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  5. interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
  6. return interceptor;
  7. }
  8. /**
  9. * 拥有lambda cache的实体类,才能使用LambdaQueryWrapper<Entity>
  10. * 默认情况下只有BaseMapper<Entity>中泛型的entity才拥有lambda cache
  11. * 其他可以通过TableInfoHelper手动添加lambda cache
  12. */
  13. @Override
  14. public void afterPropertiesSet() throws Exception {
  15. MapperBuilderAssistant assistant = new MapperBuilderAssistant(new MybatisConfiguration(),"");
  16. TableInfoHelper.initTableInfo(assistant, ExamCourseVo.class);
  17. }
  18. }

3)Mapper.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.example.jiakao.mapper.ExamCourseMapper">
  4. <resultMap id="selectCourses" type="com.example.jiakao.pojo.vo.list.ExamCourseVo">
  5. </resultMap>
  6. <!-- ${wrapper.customSqlSegment} 获取自定义SQL-->
  7. <select id="selectCourses" resultMap="selectCourses">
  8. select
  9. c.id,
  10. c.name,
  11. c.exam_place_id,
  12. c.price,
  13. c.type,
  14. e.city_id,
  15. e.province_id
  16. from exam_course c
  17. left join exam_place e on c.exam_place_id = e.id
  18. ${ew.customSqlSegment}
  19. </select>
  20. </mapper>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/830433
推荐阅读
相关标签
  

闽ICP备14008679号