paging problem in one to many query of mybatis

前言

mybatis 支持一对多的关系映射,如果需要在这种关系下,使用 pagehelper 的话,需要注意原本的 sql 以及 resultmap 的用法, 否则可能会导致 pagehelper 返回的 total 比预期的数量大。

例子

mapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<resultMap id="authorWithBlogsResult" type="AuthorWithBlogs">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="name" jdbcType="VARCHAR" property="name"/>

<collection property="blogs" ofType="Blog">
<result column="blog_id" jdbcType="BIGINT" property="id"/>
<result column="title" jdbcType="VARCHAR" property="title"/>
</collection>
</resultMap>


<select id="selectAuthorWithBlog" resultMap="authorWithBlogsResult">
select a.*,b.* from author2blog ab
inner join author a
on a.id = ab.author_id
inner join blog b
on b.id = ab.blog_id
where ab.id = #{id}
</select>

pojo

1
2
3
4
5
6
7
8
9
public class AuthorWithBlogs {
private int id;
private String name;
private List<Blog>;
public static class Blog {
private int id;
private String title;
}
}

假设现在有一个作者写了两篇文章, 调用 selectAuthorWithBlog 这个方法,会发现返回的实际数量是 1 条,但是如果使用 pagehelper 去获取 total ,返回的 total2 条,这个不难理解,上面的 sql 实际执行结果也是 2 条,pagehelper 的获取 total 也是根据对原 sql 的结果进行 count 得出的。

解决方法

嵌套 select 查询(Nested Select for Collection

将原本的关联查询,从 mapper 中抽离,使用 嵌套 select 查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<resultMap id="authorWithBlogsResult" type="AuthorWithBlogs">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="name" jdbcType="VARCHAR" property="name"/>

<collection property="blogs" ofType="Blog" select="selectBlogByAuthor" column="id">
<result column="blog_id" jdbcType="BIGINT" property="id"/>
<result column="title" jdbcType="VARCHAR" property="title"/>
</collection>
</resultMap>

<select id="selectBlogByAuthor" resultType="Blog">
select b.id as 'blog_id',b.title from author2blog ab
inner join blog b
on ab.blog_id = b.id
where ab.author_id = #{id}
</select>

<select id="selectAuthorWithBlog" resultMap="authorWithBlogsResult">
select * from author
</select>

主要修改是在 select=”selectBlogByAuthor” column=”id”

这个时候 pagehelper 的查询结果就返回正常了。

参考链接

Mybatis中如何实现一对一,一对多的关联查询

关于mybatis映射文件中表一对多时分页异常解决方法