MyBatis-plus implements three-level linkage query, joint table query processing involving paging and fuzzy query

1. Three-level linkage (taking province-city-examination room as an example)

1) table design

The same table exists for provinces and cities. A parentId of 0 represents a province, and a non-zero parentId represents a city under the corresponding province.

package com.example.jiakao.pojo.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import javax.persistence.*;

@Entity
@Data
@TableName("plate_region")
@Table(name="plate_region")
public class PlateRegionPo {
    @Id
    @TableId(type = IdType.AUTO)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column( columnDefinition = "int4" )
    private Integer id;
    @Column( columnDefinition = "varchar(64)" )
    private String name;
    @Column( columnDefinition = "varchar(64)" )
    private String plate;
    @Column( columnDefinition = "int4 default 0 " )
    private Integer parentId;
}

 Examination room table, parentId corresponds to city id

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import javax.persistence.*;

@Entity
@Data
@TableName("exam_place")
@Table(name="exam_place")
public class ExamPlacePo {
    @Id
    @TableId(type = IdType.AUTO)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column( columnDefinition = "bigint" )
    private Long id;
    @Column( columnDefinition = "varchar(64)" )
    private String name;
    @Column( columnDefinition = "int4" )
    private Integer parentId;
}

2) Define the return type vo

package com.example.jiakao.pojo.vo.list;

import lombok.Data;

import java.util.List;

@Data
public class ProvinceVo {
    private Long id;
    private String name;
    private String plate;
    private List<CityVo> children;
}
package com.example.jiakao.pojo.vo.list;

import lombok.Data;

import java.util.List;

@Data
public class CityVo {
    private Long id;
    private String name;
    private String plate;
    private List<ExamPlaceVo> children;
}
package com.example.jiakao.pojo.vo.list;

import lombok.Data;

@Data
public class ExamPlaceVo {
    private Long id;
    private String name;
}

3) mapper.xml query statement

<?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.example.jiakao.mapper.ExamPlacePoMapper">
    <resultMap id="selectRegionExamPlaces" type="com.example.jiakao.pojo.vo.list.ProvinceVo">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="plate" property="plate"></result>
        <collection property="children" ofType="com.example.jiakao.pojo.vo.list.CityVo">
            <id column="city_id" property="id"></id>
            <result column="city_name" property="name"></result>
            <result column="city_plate" property="plate"></result>
            <collection property="children" ofType="com.example.jiakao.pojo.vo.list.ExamPlaceVo">
                <id column="exam_id" property="id"></id>
                <result column="exam_name" property="name"></result>
            </collection>
        </collection>

    </resultMap>
    <select id="listRegionExamPlaces" resultMap="selectRegionExamPlaces">
        select
            p.id,
            p.name,
            p.plate,
            c.id city_id,
            c.name city_name,
            c.plate city_plate,
            e.id exam_id,
            e.name exam_name
        from plate_region p
            join plate_region c on c.parent_id = p.id
            join exam_place e on e.parent_id = c.id
        where p.parent_id = 0
    </select>
</mapper>

4) Query results

{
    "code": 200,
    "message": "成功",
    "data": [
        {
            "id": 2,
            "name": "湖北",
            "plate": "鄂",
            "children": [
                {
                    "id": 3,
                    "name": "武汉",
                    "plate": "A",
                    "children": [
                        {
                            "id": 1,
                            "name": "hfgg"
                        },
                        {
                            "id": 5,
                            "name": "hgi"
                        }
                    ]
                }
            ]
        },
        {
            "id": 1,
            "name": "广东",
            "plate": "粤",
            "children": [
                {
                    "id": 7,
                    "name": "深圳",
                    "plate": "B",
                    "children": [
                        {
                            "id": 6,
                            "name": "hgiG"
                        }
                    ]
                },
                {
                    "id": 8,
                    "name": "广州",
                    "plate": "A",
                    "children": [
                        {
                            "id": 7,
                            "name": "hgU"
                        },
                        {
                            "id": 8,
                            "name": "hgUU"
                        }
                    ]
                }
            ]
        }
    ]
}

5) Points to note

        The difference between join, left join, and right join is briefly summarized: join takes the intersection of two tables, and only keeps the intersection entries; left join uses the table before the join as the main table, regardless of whether there is an intersection or not, the main table entries exist ; Right join takes the table after join as the main table.

2. About the query processing of joint tables with fuzzy query and pagination (taking the examination room-examination subjects as an example)

1) The definition of vo is used to pass parameters when saving data, corresponding to the fields of the po object, and only ignores the fields in the po object that do not require user operations.

package com.example.jiakao.pojo.vo.req.save;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
@ApiModel("保存考场信息的参数")
public class ExamPlaceReqVo {
    @ApiModelProperty(value = "考场id")
    private Long id;
    @ApiModelProperty(value = "考场名称", required = true)
    @NotBlank(message = "名称不能为空")
    private String name;
    @ApiModelProperty(value = "考场所属城市id", required = true)
    @NotNull(message = "所属城市不能为空")
    private Integer cityId;
    @ApiModelProperty(value = "考场所属省份id", required = true)
    @NotNull(message = "所属省份不能为空")
    private Integer provinceId;
}
package com.example.jiakao.pojo.vo.req.save;

import com.example.jiakao.common.validator.BoolNumber;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
@ApiModel("保存课程信息")
public class ExamCourseReqVo {
    @ApiModelProperty("课程id")
    private Long id;
    @ApiModelProperty(value = "课程名称", required = true)
    @NotBlank(message = "课程名不能为空")
    private String name;
    @ApiModelProperty(value = "课程类型",required = true)
    @NotNull(message = "课程类型不能为空")
    @BoolNumber(message = "课程类型值为0或1")
    private Short type;
    @ApiModelProperty(value = "课程价格",required = true)
    @NotNull(message = "课程价格不能为空")
    @Min(value = 0, message = "价格不能为负数")
    private Double price;
    @ApiModelProperty(value = "课程所属考场",required = true)
    @NotNull(message = "所属考场不能为空")
    private Long examPlaceId;
}

 The vo definition of the return list is used to construct the return result entity.

package com.example.jiakao.pojo.vo.list;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel("课程信息返回值")
public class ExamCourseVo {
    @ApiModelProperty("课程id")
    private Long id;
    @ApiModelProperty(value = "课程名称")
    private String name;
    @ApiModelProperty(value = "课程类型")
    private Short type;
    @ApiModelProperty(value = "课程价格")
    private Double price;
    @ApiModelProperty(value = "课程所属考场")
    private Long examPlaceId;
    @ApiModelProperty(value = "考场所属省份")
    private Integer provinceId;
    @ApiModelProperty(value = "考场所属城市")
    private Integer cityId;
}

2) Service and Mapper

        Because there are name fields in the two tables we use, we need to clearly mark the name field of which table when constructing QueryWrapper, so we use QueryWrapper instead of LambdaQueryWrapper here.

package com.example.jiakao.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.jiakao.common.enhance.MpPage;
import com.example.jiakao.common.enhance.MpQueryWrapper;
import com.example.jiakao.mapper.ExamCourseMapper;
import com.example.jiakao.pojo.entity.ExamCoursePo;
import com.example.jiakao.pojo.vo.json.PageVo;
import com.example.jiakao.pojo.vo.list.ExamCourseVo;
import com.example.jiakao.pojo.vo.req.query.KeyWordReqVo;
import org.springframework.stereotype.Service;

@Service
public class ExamCourseService extends ServiceImpl<ExamCourseMapper, ExamCoursePo> {
    public PageVo<ExamCourseVo> listCoursesPage(KeyWordReqVo query) {
        MpPage<ExamCourseVo> mpPage= new MpPage<>(query);
        MpQueryWrapper<ExamCourseVo> wrapper = new MpQueryWrapper<>();
        wrapper.likes(query.getKeyword(),"c.name");
        baseMapper.selectCourses(mpPage,wrapper);
        return mpPage.buildVo();
    }
}  }
}
package com.example.jiakao.mapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.example.jiakao.common.enhance.MpPage;
import com.example.jiakao.pojo.entity.ExamCoursePo;
import com.example.jiakao.pojo.vo.list.ExamCourseVo;
import org.apache.ibatis.annotations.Param;

//官方推荐前缀Constants.WRAPPER => ew
public interface ExamCourseMapper extends BaseMapper<ExamCoursePo> {
    public MpPage<ExamCourseVo> selectCourses(MpPage<ExamCourseVo> page,
                                              @Param(Constants.WRAPPER) QueryWrapper wrapper);
}

        When the type we pass in and return in the Mapper method is the implementation of the IPage interface, Mybatis-plus will automatically help us paginate, that is, splice the limit after the query statement. However, the query conditions will not be automatically implemented for us. We need to manually call the customSqlSegment of the QueryWrapper type to obtain the SQL statement and then splice it into xml. Note that ${} is used for splicing instead of #{}, $ is a direct replacement, and # will be precompiled.

        Of course, we can also construct LambdaQueryWrapper for custom entities other than BaseMapper generic entities when necessary. In this case, we need to add afterPropertiesSet configuration.

public class MyBatisPlusConfig implements InitializingBean {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
        return interceptor;
    }

    /**
     * 拥有lambda cache的实体类,才能使用LambdaQueryWrapper<Entity>
     * 默认情况下只有BaseMapper<Entity>中泛型的entity才拥有lambda cache
     * 其他可以通过TableInfoHelper手动添加lambda cache
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        MapperBuilderAssistant assistant = new MapperBuilderAssistant(new MybatisConfiguration(),"");
        TableInfoHelper.initTableInfo(assistant, ExamCourseVo.class);
    }
}

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.example.jiakao.mapper.ExamCourseMapper">
    <resultMap id="selectCourses" type="com.example.jiakao.pojo.vo.list.ExamCourseVo">
    </resultMap>
<!--    ${wrapper.customSqlSegment} 获取自定义SQL-->
    <select id="selectCourses" resultMap="selectCourses">
        select
            c.id,
            c.name,
            c.exam_place_id,
            c.price,
            c.type,
            e.city_id,
            e.province_id
        from exam_course c
            left join exam_place e on c.exam_place_id = e.id
        ${ew.customSqlSegment}
    </select>
</mapper>

Guess you like

Origin blog.csdn.net/qq_33235279/article/details/130319445