MyBatis分页一对多的处理方法

文章讲述了在MyBatis中使用collection标签进行分页查询的传统方法及其缺点,如导致总记录数错误。作者推荐了在业务代码中分开查询用户和标签的正例,以及如何在特定场景下使用exists函数提高性能。
摘要由CSDN通过智能技术生成

反例

注意只探讨分页的情况,先说网上见的较多的方法

  1. collection标签

传统的方法是使用mybatis的collection标签,

 <resultMap id="MgrVOResultMap" type="com.haoyu.itlms.advanced.entity.vo.MgrAdvancedTutorVO">
        <id column="USER_ID" property="userId" jdbcType="VARCHAR"/>
        <result column="REAL_NAME" property="realName" jdbcType="VARCHAR" />
        <collection property="tagNameList" javaType="java.util.ArrayList" ofType="java.lang.String">
            <!--<id column="tag_id" property="id" jdbcType="VARCHAR" />
            <id column="tag_name" property="tagName" jdbcType="VARCHAR" />-->
            <result column="tag_name" jdbcType="VARCHAR" />
        </collection>
    </resultMap>

<sql id="mgrCommonSelectSql">
        select t.*
        from itlms_advanced_tutor t
        inner join ipanther_user u on t.user_id = u.id
        inner join ipanther_user_dept ud on u.id = ud.user_id and ud.is_deleted = 'N'
        inner join ipanther_department d on ud.dept_id = d.id
        left join itlms_advanced_tutor_tag itt on itt.user_id = t.user_id and itt.is_deleted = 'N'
    </sql>
    
 <select id="mgrPageByMap" resultMap="MgrVOResultMap">
        <include refid="mgrCommonSelectSql" />
        <include refid="BaseWhereSql" />
    </select>

这种方式在left join中就可以进行collection实现一对多,好处就是一条sql可以解决,并且也方便做转inner join表的条件查询(比如查出某个标签为“善良”的记录),但是坏处就是,假如一个user对应着3个tag,user的记录只有1条,但是分页后查询的total总是会是3,此方法没有优雅的解决办法(如果有,请在评论里告诉我谢谢),所以不推荐使用。

  1. 使用select标签
    大致是在resultMap中使用select标签,缺点是性能差一条记录一个sql,而且不能实现inner join条件查询,不推荐使用

正例

1、在业务代码中进行查询,不使用collection标签和resultMap里的select标签
思路:先查询用户列表,然后根据用户列表的id查询标签列表,遍历用户列表找符合该用户的标签

@Override
    public IPage<MgrAdvancedTutorVO> mgrPageByMap(IPage page, Map<String, Object> map) {
        
        
        // 先查询用户列表
        IPage<MgrAdvancedTutorVO> returnPage = advancedTutorMapper.mgrPageByMap(page, map);


        List<MgrAdvancedTutorVO> records = returnPage.getRecords();

        // 群体塞标签
        if(!records.isEmpty()){
        	
        	// 然后根据用户列表的id查询标签列表
            HashMap<String, Object> tagSearchMap = MapUtil.newHashMap(1);
            List<String> userIdList = records.stream().map(MgrAdvancedTutorVO::getUserId).collect(Collectors.toList());
            tagSearchMap.put("userIdList", userIdList);
            List<AdvancedTutorTag> tutorTagList = this.advancedTutorTagService.listByMap(tagSearchMap);

			// 遍历用户列表找符合该用户的标签
            for (MgrAdvancedTutorVO record : records) {
                List<AdvancedTutorTag> collect = tutorTagList.stream().filter(tutorTag -> tutorTag.getUserId().equals(record.getUserId())).collect(Collectors.toList());
                record.setTagNameList(collect.stream().map(AdvancedTutorTag::getName).collect(Collectors.toList()));
            }
        }
        return returnPage;
    }

此处只有两条sql,并不是遍历每个用户对象都查一遍sql,sql只有两条,性能好
那假如要查询符合某个标签为“善良”的记录呢?此时应该怎么处理?
此时可以使用exists函数,并且最后有个limit 1

select t.id,t.name from itlms_advanced_tutor t
where t.is_deleted = 0
<if test="cm.tagName!= null and cm.tagName!= ''">
and exists(
          select 1 from itlms_advanced_tutor_tag iatt where iatt.user_id = t.user_id and iatt.name like concat('%',#{cm.keyWord},'%') limit 1
        )
 </if>

此举即可解决此场景,且性能不会受太大影响

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用Mybatis进行一对多分页查询时,可以使用两种方式进行分页处理。 第一种方式是将分页操作放在查询语句中,这样可以根据主表的条数进行分页。然而,这种方式可能导致分页不准确,因为它以总条数进行分页,而不是以主表条数分页。 第二种方式是在service层手工进行分页处理。首先查询一次总数,然后根据当前页和每页大小计算出数据库查询的起始下标,然后将起始下标和每页大小传入查询语句中进行分页查询。这种方式比较灵活,可以根据需要进行定制化的分页操作。 另外,还可以使用MybatisPlus提供的分页功能进行一对多分页查询。可以通过创建一个Page对象,并设置每页大小和当前页数,然后调用MybatisPlus的分页查询方法来进行分页查询。 以上是Mybatis中进行一对多分页查询的两种常见方式,可以根据具体情况选择适合的方式进行操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [mybatis进阶分页(一对多)](https://blog.csdn.net/qq_32419139/article/details/121988758)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [mybatis一对多分页处理](https://blog.csdn.net/weixin_43328357/article/details/101110280)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值