在mybatis中的关联

时间:2012-08-30 08:50:43

标签: associations mybatis

我在mybatis遇到了一些问题。这是我的配置:

PostMapper.xml

<mapper namespace="com.king.model.PostMapper">
    <select id="selectById" parameterType="int" resultMap="postMap">
        select * from posts where id = #{id}
    </select>
    <select id="selectAll" resultType="hashmap">
        select * from posts order by created_at desc
    </select>

    <resultMap id="postMap" type="Post">
        <result property="createDate" column="created_at" />
        <result property="updateDate" column="updated_at" />
    </resultMap>
</mapper>

CommentMapper.xml

<mapper namespace="com.king.model.CommentMapper">
    <select id="selectById" parameterType="int" resultMap="commentMap">
        select * from comments where id = #{id} order by id desc
    </select>
    <select id="selectAll" resultMap="commentMap">
        select * from comments
    </select>
    <select id="selectByPost" resultMap="commentMap" parameterType="int">
        select * from comments where post_id=#{id}
    </select>
    <resultMap id="commentMap" type="Comment">
        <result property="createDate" column="created_at" />
        <result property="updateDate" column="updated_at" />
        <association property="post" column="post_id" javaType="Post" select="com.king.model.PostMapper.selectById" />
    </resultMap>
</mapper>


public class Post {
    private int id;
    private String title;
    private String body;
    private Date createDate;
    private Date updateDate;
    private List<Comment> comments;
}

public class Comment {
    private int id;
    private String commenter;
    private String body;
    private Post post;
    private Date createDate;
    private Date updateDate;
}

在CommentDao中:

public List<Comment> listForPost(Post post) {
    return getSqlSession().selectList("com.king.model.CommentMapper.selectByPost", post.getId());
}

然后在我的控制器中,我尝试列出一个给定帖子的所有评论:

List<Comment> coms = commentDao.listForPost(post);
post.setComments(coms)

我发现上面的代码会触发两个sql select语句:

select * from comments where post_id=? 
select * from posts where id = ? 

然而,通过mybatis 3指南,它指明在这种情况下,它会导致“N + 1”问题。

对于每个选定的评论,它将触发select语句以获取详细信息(帖子)。

但这里只有两个选择。

发生了什么事?

在mybatis中,对于一对多或多对的关联,是否应该将关系设置为双向或单向?

2 个答案:

答案 0 :(得分:0)

我没有看到任何错误。

我认为您的关系是一对多的,因为评论与单个帖子相关,而单个帖子可以有多个评论。

你的代码是正确的

List<Comment> coms = commentDao.listForPost(post);

仅触发两个查询。它将执行名为“CommentMapper.selectByPost”的查询,该查询又执行您的第一个查询,并且由于该关联,“PostMapper.selectById”是您的第二个查询。所以你向后遍历你的关系,这不会触发N + 1问题。

当您想要获取对象列表时会发生N + 1问题,每个对象都有一个相关对象列表。例如,您想获得Post的列表,并且还有他们的评论。

这意味着您执行查询以获取Post(1)列表,然后为每个Post执行查询以获取Comment(N)=&gt; N + 1

这可以解决,如果合理的话,执行单个查询,一次性返回所有注释,每个注释都有关于其Post的(冗余)信息。具有关联的MyBatis能够在该结果集上执行类似“GROUP BY”语句的操作,该语句与Post的每个实例(相关注释)相关联。

为此,您应该调用“PostMapper.selectAll”并将关联放在Post结果图中的Comment中!

答案 1 :(得分:0)

MyBatis在会话期间默认缓存语句。

由于postId没有变化,select * from posts where id = ?只会评估一次。