0

我在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>

评论映射器.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”问题。

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

但这里只有两个选择。

这是怎么回事?

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

4

2 回答 2

0

我看不出有什么问题。

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

你的代码是正确的

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

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

N+1 问题发生在您想要获取对象列表时,每个对象都有一个相关对象列表。例如,您想获取 Post 列表,并拥有他们的 Comment。

这意味着您执行查询以获取 Post (1) 的列表,然后,对于每个 Post,执行查询以获取 Comment (N) => N + 1

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

为此,您应该调用“PostMapper.selectAll”并将关联与评论放在发布结果图中!

于 2012-11-18T19:46:47.633 回答
0

MyBatis 在 Session 期间默认缓存 Statements。

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

于 2014-07-29T23:29:39.050 回答