MyBatis中的resultMap
场景
查询论坛项目首页的帖子列表
- 首先需要从MySQL数据库中多表查询到 帖子信息 和 作者信息,并得到一个 List,为了更规范我定义了一个对象 DiscussPostDTO 来定义每一项
- 但是这样还不足够,每一个帖子还有额外的 点赞数量,它存在 Redis 中
- 以及我需要列表分页,使用了 PageHelper 插件,它的分页封装对象 PageInfo 的数据集属性类型是 List
问题
现在问题来了,我应该返回给前端一个怎样的对象?
更确切地说,DiscussPostDTO 的 List 封入 PageInfo 肯定是没有问题的,关键是 likeCount 怎么塞入返回对象中?
解决方案
likeCount 肯定是每一项不同的,所以它应该被放在 DiscussPostDTO 一级,那么我返回的仍然是 PageInfo 对象确定了
为了更清楚地说明问题所在,我来描述一下被 pass 掉的方案
- 直接定义对象(不带likeCount属性)+ MyBatis SQL 语句直接返回 DiscussPostDTO 对象类型
pass,因为对象被写死了,likeCount 没法塞入对象中
那么加一个属性呢?还是直接用 resultType 的话会报字段不匹配
那么套一层 List<Map<Stirng,Object>> 呢?
可以是可以,太不好看,代码写出来太丑,而且返回结构也不好看,likeCount 独立于对象之外- MyBatis返回 map ,再往里面加一项
也可以,但还是不好看,以及每一项的结构语义不清晰,我还是希望能定义一个对象
resultMap
于是我想起来了resultType,之前是用来解决嵌套对象的问题的:一个对象属性是另一个对象的引用
像这样:
<resultMap id="course_coach2" type="com.fitness.entity.CourseInfo">
<id property="courseId" column="course_id"/>
<result property="courseName" column="course_name"/>
<result property="description" column="description"/>
<result property="startTime" column="start_time"/>
<result property="frequency" column="frequency"/>
<result property="price" column="price"/>
<result property="capacity" column="capacity"/>
<association property="courseCoach" javaType="CourseCoach">
<association property="coach" javaType="Coach">
<!-- <id property="coachId" column="coach_id"/>-->
<result property="coachName" column="coach_name"/>
</association>
</association>
</resultMap>
<select id="getAllCourseInfo" resultMap="course_coach2">
SELECT course_info.course_id, course_name,
description,
start_time,
frequency,
price,
capacity,
a.coach_name
FROM course_info
LEFT JOIN
(SELECT coach.coach_id, coach_name, course_coach.course_id
FROM coach,
course_coach
where course_coach.coach_id = coach.coach_id) a
ON course_info.course_id = a.course_id
</select>
其实刚刚这里,问题的答案就呼之欲出了
那么加一个属性呢?还是直接用 resultType 的话会报字段不匹配
用 resultMap 手动指定每个字段的匹配关系,单独留一个 likeCount 属性空着,就不会存在字段不匹配的问题
同时后面将 likeCount 封入对象时可以直接调用set
方法,方便、优雅
<resultMap id="DiscussPostDTO" type="DiscussPostVO">
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="username" column="username"/>
<result property="headerUrl" column="header_url"/>
<result property="title" column="title"/>
<result property="content" column="content"/>
<result property="type" column="type"/>
<result property="status" column="status"/>
<result property="createTime" column="create_time"/>
<result property="commentCount" column="comment_count"/>
<result property="score" column="score"/>
</resultMap>
for(DiscussPostVO discussPostVO :pageInfo.getList()){
long likeCount = likeService.findEntityLikeCount(ENTITY_TYPE_POST, discussPostVO.getId());
discussPostVO.setLikeCount(likeCount);
}