反例
注意只探讨分页的情况,先说网上见的较多的方法
- 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,此方法没有优雅的解决办法(如果有,请在评论里告诉我谢谢),所以不推荐使用。
- 使用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>
此举即可解决此场景,且性能不会受太大影响