MyBatisPlus 多表联查分页不准确的这个问题很普遍,但网上的文章一大抄,我反正没有找到靠谱的,所以把自己的方法写出来,给新手参考,请大佬指点。
话不多说,直接看例子吧:
数据库表
用户表,角色表,用户角色表
user表:user_id, user_name
role表:role_id, role_name
user_role表:id, user_id, role_id
需求
模糊查询用户姓名,分页结果,并带出角色信息(用户为多角色)。
POJO准备
/**
* 角色展示类
*/
@Data
public class RoleVO{
@ApiModelProperty(value = "角色id")
private Integer roleId;
@ApiModelProperty(value = "角色名称")
private String roleName;
}
/**
* 用户展示类
*/
@Data
public class UserVO{
@ApiModelProperty(value = "用户id")
private Integer userId;
@ApiModelProperty(value = "用户姓名")
private String userName;
@ApiModelProperty(value = "用户角色列表")
private List<RoleVO> roleList;
}
/**
* 查询类
*/
@Data
public class UserQuery{
@ApiModelProperty(value = "用户id")
private Integer userId;
@ApiModelProperty(value = "用户姓名")
private String userName;
}
Service层
public Ipage<UserVO> getListData(String userName, Integer pageNum, Integer pageSize) {
...
LambdaQueryWrapper<UserQuery> wrapper= Wrappers.lambdaQuery();
wrapper.like(UserQuery::getUserName, userName)
// 注意要Group By
.groupBy(UserQuery::getUserId);
Ipage<UserVO> pageData = userMapper.getListUser(new Page<>(pageNum, pageSize), wrapper);
}
Mapper层
IPage<UserVO> getListUser(Page page, @Param(Constants.WRAPPER) Wrapper<UserQuery> wrapper);
List<RoleVO> getListRole(String roleIdStr);
XML语句
<select id="getListUser" resultMap="getListUser">
SELECT
u.*, GROUP_CONCAT(ur.role_id) AS roleIdStr
FROM
user u
LEFT JOIN user_role ur on u.user_id = ur.user_id
${ew.customSqlSegment}
</select>
<resultMap id="getListUser" type="UserVO" >
<id column="user_id" property="userId" />
<result column="user_name" property="userName" />
<collection property="roleList" column="roleIdStr" select="getListRole"/>
</resultMap>
<select id="getListRole" resultType="RoleVO">
SELECT * FROM role WHERE FIND_IN_SET(role_id, #{roleIdStr}) > 0
</select>
总结
其实原理就是让原本一条执行的SQL拆分成多条进行。
这里因为是例子我就不展示具体SQL执行情况,简单叙述一下:
- 使用SELECT COUNT(1) 查询总记录数;
- 执行上文
getListUser
的SQL; - 执行
resultMap
中getListRole
SQL,因为涉及多个User
,所以此处会执行多次,每次查询一个User
的Role
列表。