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

问题描述

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

1、配置mybatis-plus插件

@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语句

 需求:根据年龄查询用户列表,分页显示
     *
     * 第一步: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)
    <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的子查询映射。

	<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

你可能感兴趣的:(错误收集,java,mysql,mybatis)