mybatis Result Maps对结果分组

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

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

比如微博

知乎

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

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

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

评论表

回复表

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

外连接

        SELECT articlecomment.*,articlereply.*,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="id"/>
            <result property="name" column="comment_user"/>
        </association>
        <collection property="replys" ofType="ArticleReply">
            <association property="user" javaType="User">
                <id property="id" column="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.这就需要用<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

结果

时间: 2024-08-06 15:58:01

mybatis Result Maps对结果分组的相关文章

mybatis Result Maps对结果分组2

转载请注明: TheViper http://www.cnblogs.com/TheViper  在之前的文章中说的是一个一对多情况下mybatis的自动分组,这篇说下多个一对多的情况. 比如qq空间里的说说 可以看到,说说和评论是一对多,评论又和回复是一对多. mood public class Mood { private int mood_id; private String mood_content; private String mood_time; private User user

mybatis Result Maps对结果分组3--一对多使用limit

转载请注明: TheViper http://www.cnblogs.com/TheViper  前面两篇文章都是先把多张表的结果一并取出,然后用mybatis自动分组,实现一对多的结果集.但是,实际开发过程中,是需要对评论分页的,比如在mysql中使用limit. SELECT articlecomment.articlecomment_id,articlecomment.commenttime,articlecomment.commentcontent,articlecomment.id a

Spring Boot Mybatis Result Maps collection already contains value for *.BaseResultMap

当你复制一个*Mapper.xml文件到项目工程中,运行报错Mybatis Result Maps collection already contains value for *.BaseResultMap时,教你两步解决. 1.删除对应的这个*Mapper.xml文件,启动下项目,让其报下错. 2.然后再复制文件上去,再次启动就OK了.

笔记:MyBatis Mapper XML文件详解 - Result Maps

Result Maps(结果集) resultMap 元素是 MyBatis 中最重要最强大的元素.它就是让你远离 90%的需要从结果 集中取出数据的 JDBC 代码的那个东西, 而且在一些情形下允许你做一些 JDBC 不支持的事 情. 事实上, 编写相似于对复杂语句联合映射这些等同的代码, 也许可以跨过上千行的代码. ResultMap 的设计就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们 的关系,你已经看到简单映射语句的示例了,但没有明确的 resultMap.比如: <s

MyBatis 3.2.8 用户手册 4.1.5 Result Maps

明明如月 QQ  605283073 本科英语翻译专业  研究生  软件工程专业  爱好JAVA 学习2年+ 纯粹爱好,利用业余时间翻译.首次尝试翻译  有不足请见谅. 4.1.5 Result Maps 结果映射(ResultMap) 是 MyBatis框架中最重要和强大的元素. 它为你节省从JDBC结果集中获取数据90%的代码,在某些情况下甚至提供给JDBC都不支持的功能. 实际上,写一些比如含有join的复杂语句映射的等价代码甚至需要上千行代码.结果映射(ResultMaps)设计的简洁语

MyBatis错误:Result Maps collection already contains value for novel.storage.mapper.NovelMapper.BaseResultMap

今天在写项目的时候遇到一个问题如下: org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession.### The error may exist in NovelMapper.xml### The error occurred while processing mapper_resultMap[BaseResultMap]### Cause: org.apache.ibatis.builder.

A query was run and no Result Maps were found for...原来是mapper.xml文件出了问题,是使用MyBatis最常见的一种错误

今天遇到一个问题,原来是mapper.xml文件出了问题,是使用MyBatis最常见的一种错误 报错的结果是这样的: A query was run and no Result Maps were found for the Mapped Statement 'cn.zrgk.dao.RoleMapper.getRoleList'. It's likely that neither a Result Type nor a Result Map was specified. org.apache.

mybatis中Invalid bound statement (not found) 和 Result Maps collection already contains value for...错误解决方案

一.Invalid bound statement (not found) 使用mybatis有时候会报Invalid bound statement (not found)这种错误,总结了下,可能有两种情况如下: 1.mybatis的对应的mapper.xml找不到对应的命名sql或者名称与mapper接口名称不一致. 2.xml文件与接口名称都对,但是在mybatis配置文件中漏掉了配置,也会报这种错误. 二.Result Maps collection already contains v

mybatis配置文件xxxx.xml中缺失返回类型的后果A query was run and no Result Maps were found

使用mybatis时出现异常问题: 有如下的错误 Error querying database.  Cause: org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement (后面内容省略) 网上说是oracle不允许插入空值. 但是我没有进行插入操作的,只是进行了查询. 后来看看mybatis的配置文件,漏了一项:res