zoukankan      html  css  js  c++  java
  • mybatis Result Maps对结果分组1--一对多

    转载请注明: TheViper http://www.cnblogs.com/TheViper 

    一对多的关系,比如文章和评论,这时需要展示文章和评论,并按文章分组。很多时候,页面只显示评论数,如果用户要看具体评论,就要点击评论数的链接。

    比如微博

    知乎

    如果一定要在展示文章(或微博)时,显示前几条评论该怎么做呢?(这里不讨论mongodb)

    一个常见的做法是对一方,外连接多方,一并取出,然后手工遍历分组。

    这里还是以文章评论和回复为例

    评论表

    回复表

    两个表的id字段分别表示评论的用户id和回复的用户id,articlereplay表的comment_id是外键.另外还有个user表(id,name)。

    外连接

            SELECT articlecomment.articlecomment_id,articlecomment.commenttime,articlecomment.commentcontent,articlecomment.id as commentuser_id
            ,articlereply.articlereply_id,articlereply.replytime,articlereply.replycontent,articlereply.id as replyuser_id
            ,u1.name AS comment_user,u2.name AS reply_user FROM articlecomment 
            LEFT JOIN articlereply ON articlereply.comment_id=articlecomment.articlecomment_id INNER JOIN USER AS u1 ON u1.id=articlecomment.id 
            INNER JOIN USER AS u2 ON u2.id=articlereply.id ORDER BY commenttime DESC,replytime DESC    

    实际上这里不用写代码遍历结果,进行分组。用mybatis的resultmap就可以很优雅的帮我们按评论分好组。

    ArticleComment类

    public class ArticleComment {
        private int articlecomment_id;
        private String commentcontent;
        private String commenttime;
        private User user;
        private Article article;
        private List<ArticleReply> replys;
            //getter,setter  
    }

    ArticleReply类

    public class ArticleReply {
        private int articlereply_id;
        private String replycontent;
        private String replytime;
        private User user;
            //setter,getter
    }

    resultmap

        <resultMap id="ArticleCommentResult" type="ArticleComment">
            <id property="articlecomment_id" column="articlecomment_id" />
            <association property="user" javaType="User">
                   <id property="id" column="commentuser_id"/>
                <result property="name" column="comment_user"/>
            </association>
            <collection property="replys" ofType="ArticleReply">
                <association property="user" javaType="User">
                    <id property="id" column="replyuser_id" />
                    <result property="name" column="reply_user"/>
                </association>
            </collection>
        </resultMap>

    从“一”(articlecomment)那边取"多"(articlereply).注意,<association>要放到<collection>前面,否则报错。

    org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 16; columnNumber: 14; 元素类型为 "resultMap" 的内容必须匹配 "(constructor?,id*,result*,association*,collection*,discriminator?)"。

    pojo的类属性名尽量和数据库相应表的字段名一致,参见本屌的文章mybatis3 autoMappingBehavior

    另外这里的两个表都内连接User表获取用户名,因此在sql中分别重命名为comment_user,reply_user.id也一样。这里重命名为commentuser_id,replyuser_id.这就需要用<result>调整,使被重命名的字段和pojo类属性名相对应。

    效果

    问题又来了,上面是把回复全部选出来了,实际需求可能是只选取离当前时间最近的5条回复,如果用户想看到更多回复,就需要点“加载更多”。这又该怎么做?

    参见本屌翻译的(译)如何在sql中选取每一组的第一行/最后行/前几行

            SELECT articlecomment.*,articlereply1.* FROM articlecomment 
            LEFT JOIN 
            (SELECT *
            FROM articlereply
            WHERE (
                   SELECT COUNT(*) FROM articlereply AS f
                   WHERE f.comment_id = articlereply.comment_id AND f.replytime >= articlereply.replytime
                  ) <= 2
             ) AS articlereply1
             ON articlereply1.comment_id=articlecomment.articlecomment_id ORDER BY articlereply1.replytime DESC

    left join一个子查询,从articlereply表中选出每组离当前世界最近的2条回复,其他的和前面的外连接查询一样。

    另外,如果用(译)如何在sql中选取每一组的第一行/最后行/前几行里面提到的user variables方法,实际上就是把上面sql里面left join后articlereply子查询写成user variables形式。但这就有个问题,每组的row_number会依次递增,而我们需要的是order by replytime desc,和row_number的顺序相反.

    结果

    上面查询没有对row_number进行过滤,这时如果WHERE x.row_number<=2,得到的结果与我们想要的相反。

    这时很容易想到把row_number的顺序反过来,不过本屌不知道怎么修改if(@type = type, @num + 1, 1)。没办法只有用子查询了。

    SELECT *
    FROM (
       SELECT articlereply.*,
          @num := IF(@type =comment_id, @num + 1, 1) AS row_number,
          @type := comment_id AS dummy
       FROM articlereply 
    ) AS X WHERE x.row_number>=(SELECT COUNT(*) FROM articlereply WHERE articlereply.comment_id=x.comment_id
      GROUP BY articlereply.comment_id)-1

    结果

  • 相关阅读:
    【HDU2222】Keywords Search(AC自动机)
    -网络流题表
    【 POJ
    【 UVALive
    【POJ2699】The Maximum Number of Strong Kings(网络流)
    【UVALive
    【HDU3081】Marriage Match II (二分+最大流)
    【UVALive
    【LA2796】Concert Hall Scheduling(最大费用最大流)
    【 UVALive
  • 原文地址:https://www.cnblogs.com/TheViper/p/4604640.html
Copyright © 2011-2022 走看看