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>

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)

そして、上記のコードが2つのSQL選択ステートメントをトリガーすることがわかりました:

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

ただし、mybatis 3 ガイドでは、このスイートでは "N+1" 問題が発生することが明記されています。

選択されたコメントごとに、詳細 (投稿) の選択ステートメントがトリガーされます。

ただし、ここでは 2 つだけ選択します。

どうしたの?

また、mybatis では、1 対多または多対多の関連付けに対して、リレーションを双方向または単方向として設定する必要がありますか?

4

2 に答える 2

0

MyBatis は、デフォルトでセッション中にステートメントをキャッシュします。

postId は変更select * from posts where id = ?されないため、一度だけ評価されます。

于 2014-07-29T23:29:39.050 に答える
0

私はそれで何も悪いとは思いません。

コメントは単一の投稿に関連しているのに対し、単一の投稿には複数のコメントを含めることができるため、あなたの関係は一対多であると思います。

あなたのコードは正しいです

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

2 つのクエリのみをトリガーします。「CommentMapper.selectByPost」という名前のクエリが実行され、これが最初のクエリを実行し、関連付けにより、2 番目のクエリである「PostMapper.selectById」が実行されます。したがって、関係を逆方向にたどっていますが、これは N+1 問題を引き起こしません。

N+1 問題は、オブジェクトのリストを取得したい場合に発生します。各オブジェクトには、関連するオブジェクトのリストがあります。たとえば、投稿のリストを取得し、そのコメントも取得したいとします。

これは、クエリを実行して投稿 (1) のリストを取得し、次に各投稿に対してコメント (N) を取得するクエリを実行することを意味します => N + 1

これは、合理的であれば、すべてのコメントを一度に返す単一のクエリを実行することで解決できます。各コメントには、投稿に関する (冗長な) 情報が含まれています。関連付けを持つ MyBatis は、その結果セットに対して "GROUP BY" ステートメントのようなことを行うことができます。これは、関連するコメントである Post の各インスタンスに関連付けられます。

これを行うには、「PostMapper.selectAll」を呼び出して、Post 結果マップの Comment への関連付けを配置する必要があります。

于 2012-11-18T19:46:47.633 に答える