mybatis-3中文文档
一个博客
只会关联一个作者
;
一个博客
中可以有多个文章
;
一个文章
可以有多个评论
;(暂时不考虑父子级评论)
一个文章
也可以有多个标签
;
关系如下图
<resultMap id="detailedBlogResultMap" type="Blog">
<constructor>
<idArg column="blog_id" javaType="int"/>
constructor>
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
<result property="favouriteSection" column="author_favourite_section"/>
association>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<association property="author" javaType="Author"/>
<collection property="comments" ofType="Comment">
<id property="id" column="comment_id"/>
collection>
<collection property="tags" ofType="Tag" >
<id property="id" column="tag_id"/>
collection>
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
discriminator>
collection>
resultMap>
<select id="selectBlogDetails" resultMap="detailedBlogResultMap">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
A.bio as author_bio,
A.favourite_section as author_favourite_section,
P.id as post_id,
P.blog_id as post_blog_id,
P.author_id as post_author_id,
P.created_on as post_created_on,
P.section as post_section,
P.subject as post_subject,
P.draft as draft,
P.body as post_body,
C.id as comment_id,
C.post_id as comment_post_id,
C.name as comment_name,
C.comment as comment_text,
T.id as tag_id,
T.name as tag_name
from Blog B
left outer join Author A on B.author_id = A.id
left outer join Post P on B.id = P.blog_id
left outer join Comment C on P.id = C.post_id
left outer join Post_Tag PT on PT.post_id = P.id
left outer join Tag T on PT.tag_id = T.id
where B.id = #{id}
select>
先看如果使用连接查询,它们的数据大致可以如下描述,可以看出来mybatis提供的强大的数据封装能力:
文章A 评论1 (A 有评论1、评论2、评论3)
文章A 评论1
文章A 评论2
文章B 评论4 (B 有评论1)
文章B 评论4
Post{ List<Comment> comments }
-------------------------
文章A 评论1 标签a (A 有评论1、评论2、评论3;标签a、标签b)
文章A 评论1 标签b
文章A 评论2 标签a
文章A 评论2 标签b
文章A 评论3 标签a
文章A 评论3 标签b
文章B 评论4 标签a (B 有评论1;标签a、标签b)
文章B 评论4 标签b
Post{ List<Comment> comments, List<Tag> tags }
-------------------------
博客Ⅰ 文章A 评论1 (博客Ⅰ 有文章A、文章B;文章A 有评论1、评论2、评论3)
博客Ⅰ 文章A 评论2
博客Ⅰ 文章A 评论3
博客Ⅰ 文章B 评论4
博客Ⅱ 文章C 评论5 (博客Ⅱ 有文章C;文章C 有评论5、评论6)
博客Ⅱ 文章C 评论6
Blog{ List<Post> posts},Post{ List<Comment> comments}
-------------------------
博客Ⅰ 文章A 评论1 标签a (博客Ⅰ 有文章A、文章B;文章A 有评论1、评论2、评论3;文章A 有标签a、标签b)
博客Ⅰ 文章A 评论1 标签b
博客Ⅰ 文章A 评论2 标签a
博客Ⅰ 文章A 评论2 标签b
博客Ⅰ 文章A 评论3 标签a
博客Ⅰ 文章A 评论3 标签b
博客Ⅰ 文章B 评论4 标签a
博客Ⅰ 文章B 评论4 标签b
博客Ⅱ 文章C 评论5 标签a (博客Ⅱ 有文章C;文章C 有评论5、评论6;文章C 有标签a、标签b))
博客Ⅱ 文章C 评论6 标签a
Blog{ List<Post> posts},Post{ List<Comment> comments, List<Tag> tags }
查询指定id的博客,并且查询出这个博客的作者
。
<select id="selectAuthor" resultType="Author">
SELECT * FROM AUTHOR WHERE ID = #{id}
select>
<resultMap id="blogResult" type="Blog">
<association property="author" column="author_id" javaType="Author" select="selectAuthor"/>
resultMap>
<select id="selectBlog" resultMap="blogResult">
SELECT * FROM BLOG WHERE ID = #{id}
select>
依然是:查询指定id的博客,并且查询出这个博客的作者
。
但是mybatis给出了另外一种映射方案,我们可以使用连接查询的方式,并且修改映射方式。
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
association>
resultMap>
<select id="selectBlog" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
A.id as author_id,
A.username as author_username,
A.password as author_password,
A.email as author_email,
A.bio as author_bio
from
Blog B
left outer join Author A on B.author_id = A.id
where
B.id = #{id}
select>
查询指定id的博客,并且查询该博客下的所有文章
<select id="selectPostsForBlog" resultType="Post">
SELECT * FROM POST WHERE BLOG_ID = #{id}
select>
<resultMap id="blogResult" type="Blog">
<collection property="posts" javaType="ArrayList"
column="id" ofType="Post" select="selectPostsForBlog"/>
resultMap>
<select id="selectBlog" resultMap="blogResult">
SELECT * FROM BLOG WHERE ID = #{id}
select>
依然是:查询指定id的博客,并且查询该博客下的所有文章
。
但是mybatis给出了另外一种映射方案,我们可以使用连接查询的方式,并且修改映射方式。
<resultMap id="blogResult" type="Blog">
<id property="id" column="blog_id" />
<result property="title" column="blog_title"/>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
collection>
resultMap>
<select id="selectBlog" resultMap="blogResult">
select
B.id as blog_id,
B.title as blog_title,
B.author_id as blog_author_id,
P.id as post_id,
P.subject as post_subject,
P.body as post_body,
from
Blog B
left outer join Post P on B.id = P.blog_id
where
B.id = #{id}
select>
虽然这种方式避免了N+1的问题,但是我们应当注意到,当我们需要对主表,比如说Blog表,进行分页查询时,这个时候,使用上面的集合的嵌套结果映射
就有问题了。假设我们使用的PageHelper分页插件,一个Blog查出来,它会对应好多个文章,也就是数据库中的一条Blog记录,但是这条Blog记录连接查询后的结果,由于一对多的关系,形成了多条Blog记录(一个Blog记录对应多个文章),那这里这么分页肯定就不对了,因此,这种情况,只能用上面的集合的嵌套Select查询
,因为PageHelper是把分页信息存储在ThreadLocal中,并且只会在开启分页后第一次执行查询时才会拼接分页sql,因此,后面的嵌套Select查询就没分页了。