mybatisplus 自定义mapper加多表联查结合分页插件查询时出现缺失数据的问题

问题描述

最近做项目时使用了mybatisplus,分页插件也使用的是mybatisplus自带的分页插件,业务需求是查询客户列表,每个客户列表中有一个子列表 ,在通过分页插件查询后,会出现数量总数为子列表总数、客户列表与子列表不对等。

1、配置mybatis-plus插件

java 复制代码
@Configuration
@MapperScan("com.guigu.mapper") //可以将启动类中的注解移到此处
public class MybatisPlusConfig {
    /**
     *
     * 1 怎么来配置mybatis-plus中的插件?
     *   这里所需要的类型是MybatisPlusInterceptor,这是mybatis-plus的一个拦截器,用于配置mybatis-plus中的插件。
     * 2 为什么要使用拦截器MybatisPlusInterceptor呢?
     *    这里边的原理和mybatis分页插件的功能是一样的,工作流程如下 :
     *   (1)第一步:执行查询功能。
     *   (2)第二步:拦截器对查询功能进行拦截。
     *   (3)第三步:拦截器对查询功能的基础上做了额外的处理,达到分页的效果(功能)。
     * 3 对比配置mybatis中的插件?
     *   用的也是拦截器的方式。
     *
     * @return MybatisPlusInterceptor
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加:分页插件
        //参数:new PaginationInnerInterceptor(DbType.MYSQL),是专门为mysql定制实现的内部的分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

2、mapper语句

java 复制代码
 需求:根据年龄查询用户列表,分页显示
     *
     * 第一步:xml自定义分页,Mapper接口方法
     *       第1步:如果想要mybatis-plus的分布插件来作用于我们自定义的sql语句的话,
     * 		第一个参数必须得是一个分页对象:@Param("page") Page<User> page。
     * 第二步:因为Mapper接口方法有2个参数的话
     *       方案1:使用mybatis提供的访问方式
     *       方案2:也可以使用@param来设置命名参数,来规定参数的访问规则
    Page<CustomerEntity> queryCustomerList(@Param("page") Page<CustomerEntity> customerPage,
                                           @Param("customerName") String customerName,
                                           @Param("deptIds") List<Long> deptIds,
                                           @Param("userIds") List<Long> userIds,
                                           @Param("delFlag") Integer logicNotDeleteValue)
xml 复制代码
    <resultMap id="customerList" type="customerEntity">
        <id property="customerId" column="customer_id"/>
        <result property="customerName" column="customer_name"/>
        <collection property="children" select="queryList" column="customer_id" ofType="customerInfoEntity">
        </collection>
        <collection property="children" ofType="customerInfoEntity">
            <id property="customerInfoId" column="customer_info_id"/>
            <result property="customerId" column="customer_id"/>
            <result property="deptId" column="dept_id"/>
            <result property="industry" column="industry"/>
            <result property="level" column="level"/>
            <result property="source" column="source"/>
            <result property="highSeas" column="high_seas"/>
            <result property="remark" column="remark"/>
            <result property="crtTime" column="crt_time"/>
            <result property="crtName" column="crt_name"/>
            <result property="crtUserId" column="crt_user_id"/>
        </collection>
    </resultMap>
    <select id="queryCustomerList" resultMap="customerList">
        SELECT
        c.customer_id,
        c.customer_name,
        ci.customer_info_id,
        ci.customer_id,
        ci.dept_id,
        ci.industry,
        ci.level,
        ci.source,
        ci.high_seas,
        ci.remark,
        ci.crt_time,
        ci.crt_name,
        ci.crt_user_id
        FROM customer c
        JOIN customer_info ci on c.customer_id = ci.customer_id
        where ci.high_seas = 0
        and ci.del_flag = #{delFlag}
        and c.del_flag =#{delFlag}
        <if test="customerName != null">
            AND c.customer_name like concat('%',#{customerName},'%')
        </if>
        <if test="deptIds.size>0">
            AND ci.dept_id in
            <foreach collection="deptIds" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
        </if>
        <if test="userIds.size>0">
            AND ci.crt_user_id in
            <foreach collection="userIds" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
        </if>
    </select>

上述语句查询的结果数是表customer_info 的数量而不是表customer的数量,客户列表下有多个子列表时会分成多个相同的客户。

解决办法

那我们怎么才能查到正确得一对多的分页结果呢?mybatis提供另一种方式,使用mybatis的子查询映射。

java 复制代码
	<resultMap id="customerList" type="customerEntity">
        <id property="customerId" column="customer_id"/>
        <result property="customerName" column="customer_name"/>
        <collection property="children" select="queryList" column="customer_id" ofType="customerInfoEntity">
        </collection>
    </resultMap>

    <select id="queryList" resultType="customerInfoEntity">
        select ci.customer_info_id,
               ci.customer_id,
               ci.dept_id,
               ci.industry,
               ci.level,
               ci.source,
               ci.high_seas,
               ci.remark,
               ci.crt_time,
               ci.crt_name,
               ci.crt_user_id
        from customer_info ci
        where ci.customer_id = #{customer_id};
    </select>

    <!--    查询未加入公海池的客户列表-->
    <select id="queryCustomerList" resultMap="customerList">
        SELECT
        c.customer_id,
        c.customer_name,
        ci.customer_info_id,
        ci.customer_id,
        ci.dept_id,
        ci.industry,
        ci.level,
        ci.source,
        ci.high_seas,
        ci.remark,
        ci.crt_time,
        ci.crt_name,
        ci.crt_user_id
        FROM customer c
        JOIN customer_info ci on c.customer_id = ci.customer_id
        where ci.high_seas = 0
        and ci.del_flag = #{delFlag}
        and c.del_flag =#{delFlag}
        <if test="customerName != null">
            AND c.customer_name like concat('%',#{customerName},'%')
        </if>
        <if test="deptIds.size>0">
            AND ci.dept_id in
            <foreach collection="deptIds" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
        </if>
        <if test="userIds.size>0">
            AND ci.crt_user_id in
            <foreach collection="userIds" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
        </if>
    </select>

注意: collection中的colum属性需要填两表关联的字段,也就是customer_id

相关推荐
毕设源码-朱学姐5 小时前
【开题答辩全过程】以 工厂能耗分析平台的设计与实现为例,包含答辩的问题和答案
java·vue.js
Spring AI学习7 小时前
Spring AI深度解析(9/50):可观测性与监控体系实战
java·人工智能·spring
java1234_小锋7 小时前
Spring IoC的实现机制是什么?
java·后端·spring
xqqxqxxq8 小时前
背单词软件技术笔记(V2.0扩展版)
java·笔记·python
消失的旧时光-19438 小时前
深入理解 Java 线程池(二):ThreadPoolExecutor 执行流程 + 运行状态 + ctl 原理全解析
java·开发语言
哈哈老师啊8 小时前
Springboot学生综合测评系统hxtne(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
java·数据库·spring boot
4311媒体网8 小时前
帝国cms调用文章内容 二开基本操作
java·开发语言·php
梁萌8 小时前
MySQL数据库分库分表介绍
数据库·mysql·shardingsphere·分库分表
zwxu_9 小时前
Nginx NIO对比Java NIO
java·nginx·nio
可观测性用观测云10 小时前
Pyroscope Java 接入最佳实践
java