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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Mybatis-Plus提供了非常方便的多表查询分页的方法,可以通过Wrapper构造器实现。 假设我们有两个表t_user和t_order,t_user中有user_id和username两个字段,t_order中有order_id和user_id两个字段,我们需要查询t_user中username包含"张三"、t_order中user_id为1的订单,并且按照order_id排序。可以通过如下代码实现: ```java // 创建分页对象 IPage<Order> page = new Page<>(1, 10); // 构造查询条件 QueryWrapper<Order> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_id", 1) .orderByAsc("order_id"); // 执行查询 List<Order> orders = orderMapper.selectPage(page, queryWrapper).getRecords(); ``` 如果需要关联查询t_user表中的用户信息,可以使用左连接关联查询,如下: ```java // 创建分页对象 IPage<OrderVo> page = new Page<>(1, 10); // 构造查询条件 QueryWrapper<OrderVo> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("o.user_id", 1) .like("u.username", "张三%") .orderByAsc("o.order_id"); // 执行查询 List<OrderVo> orderVos = orderMapper.selectOrderVoPage(page, queryWrapper); ``` 其中,OrderVo是一个自定义的实体类,用于接收关联查询的结果,可以通过@TableName指定对应的表名,@TableField指定对应的字段名。同,需要在OrderMapper中定义selectOrderVoPage方法,实现关联查询,如下: ```java List<OrderVo> selectOrderVoPage(IPage<OrderVo> page, @Param(Constants.WRAPPER) Wrapper<OrderVo> wrapper); ``` 需要注意的是,OrderVo中的字段名需要与查询条件中的别名一致,否则查询结果为null。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值