我在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中,对于一对多或多对的关联,是否应该将关系设置为双向或单向?
答案 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 = ?
只会评估一次。