mybatis collection标签_一对多的关系,在MyBatis中如何映射?

# 使用collection标签

需求:根据用户id查询用户信息的同时获取用户拥有的角色,一个用户可以拥有1个或多个角色。

一般情况下,不建议直接修改数据库表对应的实体类。

所以这里我们延用之前博客中新建的类SysUserExtend,并添加如下代码,如下所示:

/** * 用户的角色集合 */private List sysRoleList;public ListgetSysRoleList() {    return sysRoleList;}public void setSysRoleList(List sysRoleList) {    this.sysRoleList = sysRoleList;}

然后,我们在接口SysUserMapper中添加如下方法:

/** * 获取所有的用户以及对应的所有角色 * * @return */List selectAllUserAndRoles();

接着,在对应的SysUserMapper.xml中添加如下代码:

<resultMap id="userRoleListMap" type="com.zwwhnly.mybatisaction.model.SysUserExtend" extends="sysUserMap">    <collection property="sysRoleList" columnPrefix="role_"                ofType="com.zwwhnly.mybatisaction.model.SysRole">        <id property="id" column="id"/>        <result property="roleName" column="role_name"/>        <result property="enabled" column="enabled"/>        <result property="createBy" column="create_by"/>        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>    collection>resultMap>

因为我们在前面的博客中已经建过角色表的roleMap:

<resultMap id="roleMap" type="com.zwwhnly.mybatisaction.model.SysRole">    <id property="id" column="id"/>    <result property="roleName" column="role_name"/>    <result property="enabled" column="enabled"/>    <result property="createBy" column="create_by"/>    <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>resultMap>

所以上面的collection标签可以简化为:

<collection property="sysRoleList" columnPrefix="role_"            resultMap="com.zwwhnly.mybatisaction.mapper.SysRoleMapper.roleMap">collection>

新建接口对应的查询代码,使用上面新建的userRoleListMap,如下所示:

    SELECT        u.id,        u.user_name,        u.user_password,        u.user_email,        u.create_time,        r.id role_id,        r.role_name role_role_name,        r.enabled role_enabled,        r.create_by role_create_by,        r.create_time role_create_time    FROM sys_user u    INNER JOIN sys_user_role ur ON u.id = ur.user_id    INNER JOIN sys_role r ON ur.role_id = r.id

最后,在SysUserMapperTest测试类中添加如下测试方法:

@Testpublic void testSelectAllUserAndRoles() {    SqlSession sqlSession = getSqlSession();    try {        SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);        List sysUserList = sysUserMapper.selectAllUserAndRoles();        System.out.println("用户数:" + sysUserList.size());        for (SysUserExtend sysUser : sysUserList) {            System.out.println("用户名:" + sysUser.getUserName());            for (SysRole sysRole : sysUser.getSysRoleList()) {                System.out.println("角色名:" + sysRole.getRoleName());            }        }    } finally {        sqlSession.close();    }}

运行测试代码,测试通过,输出日志如下:

DEBUG [main] - ==> Preparing: SELECT u.id, u.user_name, u.user_password, u.user_email, u.create_time, r.id role_id, r.role_name role_role_name, r.enabled role_enabled, r.create_by role_create_by, r.create_time role_create_time FROM sys_user u INNER JOIN sys_user_role ur ON u.id = ur.user_id INNER JOIN sys_role r ON ur.role_id = r.idDEBUG [main] - ==> Parameters:TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time, role_id, role_role_name, role_enabled, role_create_by, role_create_timeTRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0, 1, 管理员, 1, 1, 2019-06-27 18:21:12.0TRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0, 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0TRACE [main] - <== Row: 1001, test, 123456, test@mybatis.tk, 2019-06-27 18:21:07.0, 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0DEBUG [main] - <== Total: 3用户数:2用户名:admin角色名:管理员角色名:普通用户用户名:test角色名:普通用户

# MyBatis合并规则

观察上面的日志,我们的Sql语句查询到了3条数据,在数据库查询的话,也是返回如下的数据:

a65145e3daeeeb420412a660594f14ad.png

但经过MyBatis配置的映射到,最后合并为了2个用户,其中第1个用户包含了2个角色,第2个用户包含了1个角色,那么MyBatis是根据什么规则合并的呢?

MyBatis在处理结果的时候,会判断结果是否相同,如果是相同的结果,则只会保留第一个结果,所以关键点就是MyBatis如何判断结果是否相同。

判断结果是否相同时,最简单的情况就是在映射配置中至少有1个id标签,上面使用的sysUserMap就配置了id标签:

<id property="id" column="id"/>

一般情况下,id标签配置的字段为表的主键,如果是联合主键,可以配置多个id标签。

id标签的作用就是在嵌套的映射配置时判断数据是否相同,当配置id标签时,MyBatis只需要逐条比较所有数据中id标签配置的字段值是否相同即可。

也可以不配置id标签,将上面的代码修改为:

<result property="id" column="id"/>

使用result不会影响查询结果,但是此时MyBatis就要对所有字段进行比较,因此当字段数为M时,如果查询结果有N条,就需要比较M*N次,如果配置了id标签,只需要比较N次即可,所以要尽可能的配置id标签。

结合上面的例子,因为Sql的查询结果中,前2条数据中用户的id是相同的,所以会合并为1个用户,所以最终的结果是2个用户。

为了更清楚的理解id标签的作用,我们将sysUserMap临时修改为:

<resultMap id="sysUserMap" type="com.zwwhnly.mybatisaction.model.SysUser">    <id property="userPassword" column="user_password"/>    <result property="id" column="id"/>    <result property="userName" column="user_name"/>    <result property="userEmail" column="user_email"/>    <result property="userInfo" column="user_info"/>    <result property="headImg" column="head_img" jdbcType="BLOB"/>    <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>resultMap>

运行测试方法,输出的部分日志如下:

用户数:1用户名:admin角色名:管理员角色名:普通用户

因为3个用户的密码都是123456,所以查询到的3条数据只保留了第一个用户admin,包含了2个角色。

有的同学也许会问,为什么不是拥有3个角色呢?

这是因为MyBatis会对嵌套查询的每一级对象都进行属性比较,MyBatis会先比较顶层的对象,如果SysUser部分相同,就继续比较SysRole部分,如果SysRole不同,就会增加一个SysRole,如果相同就保留前一个。

如果SysRole还有下一级,依次按照规则去比较。

上面的“普通用户”角色重复了,所以只保留了前1个,导致最终的结果中只包含2个角色而不是3个。

#  源码及参考

  • 源码地址:https://github.com/zwwhnly/mybatis-action.git,欢迎下载。

  • 刘增辉《MyBatis从入门到精通》

作者:申城异乡人

来源:https://www.cnblogs.com/zwwhnly/p/11194028.html

 往期推荐 

?

  • Github移动端,IDEA 2019.3.4,JDK 14,都发布了,赶快尝鲜
  • MyBatis中如何使用association标签实现嵌套查询
  • 有点惨!百度工程师挖矿:4 个月控制 155 台服务器挖矿,获利 10万,被判 3 年

ab3953724e94228c44493b02ca3fe800.png

9157e860479260e6ef08d834c9eea8b8.gif 

点击

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/304734.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

上传文件白名单_十大常见web漏洞——文件上传漏洞

漏洞介绍在我们浏览网页时&#xff0c;文件上传是非常常见的&#xff0c;比如我们会上传头像、附件、视频等文件&#xff0c;文件上传漏洞通常由于网页代码中的文件上传路径变量过滤不严造成的&#xff0c;如果文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型…

Java编程比C编程好吗?《精通Unix下C语言与项目实践》读书笔记(15)

《精通Unix下C语言编程与项目实践》读书笔记(new)文章试读 不拘一个遍程序系列&#xff1a;编程序不能一个脑袋钻到底&#xff0c;有时要学会变通&#xff0c;即所谓的曲线救国。一、二、三、四职场规划&#xff1a;一些杂七杂八的职场感悟吧。不值钱的软件人才 精力充沛与事业…

C# Lambda表达式详解,及Lambda表达式树的创建

每次写博客&#xff0c;第一句话都是这样的&#xff1a;程序员很苦逼&#xff0c;除了会写程序&#xff0c;还得会写博客&#xff01;当然&#xff0c;希望将来的一天&#xff0c;某位老板看到此博客&#xff0c;给你的程序员职工加点薪资吧&#xff01;因为程序员的世界除了苦…

将span隐藏的函数_分类汇总函数Subtotal和Aggregate应用技巧解读

在实际的数据统计分析中&#xff0c;经常会遇到很多复杂的因素&#xff0c;例如&#xff0c;对隐藏的行或计算结果返回错误类型的值不予统计等等……如果此时还用常规的Sum系列、Count系列、Average系列等函数去做数据统计分析&#xff0c;将会是难上加难或者根本无法完成。此时…

粉丝回馈 | 用30天换来了这辈子独一无二的纪念

不知不觉2017年已经临近尾声了&#xff0c;超模君和小木决定趁年末&#xff0c;要给粉丝们一份用心的回馈&#xff0c;感谢这一年来大家对我们的支持与厚爱~ 经过几天几夜的苦思冥想、辗转反侧。。。超模君和小木最终确定了一份超模定制版纪念品&#xff0c;定制版&#xff01;…

地图统计_连吃七八个都不够!太仓不完整包子统计地图来了!

在上班的路上总会顺道买上几个包子&#xff0c;不止是因为方便美味&#xff0c;圆鼓鼓的外型就像个太阳一样能带来满满的能量。这次叔打卡了8家高人气包子店&#xff0c;不知道有没有你经常光顾的那家呢&#xff1f;留言区还抽3位吃货送现金红包哦&#xff01;长春路包子铺?地…

使用 Tye 辅助开发 k8s 应用竟如此简单(四)

使用 Tye 辅助开发 k8s 应用竟如此简单&#xff08;一&#xff09;使用 Tye 辅助开发 k8s 应用竟如此简单&#xff08;二&#xff09;使用 Tye 辅助开发 k8s 应用竟如此简单&#xff08;三&#xff09;续上篇&#xff0c;这篇我们来进一步探索 Tye 更多的使用方法。本篇我们来了…

炸锅了!Google称2029年人类开始实现永生不死!疾病,衰老,痛苦将彻底消失!?

这个世界上最公平的&#xff0c;恐怕就是生老病死了。即使一个人一生的成就再大&#xff0c;财富再多&#xff0c;最终都敌不过自然规律&#xff0c;走向死亡。 然而 谷歌的首席未来科学家Ray kurzweil 却发布了一个惊天消息&#xff1a; 到了2029年&#xff0c; 人类将开始正…

asp.net web api中的版本管理

应用是演进的&#xff0c;通常我们用版本号来管理。api也是演进的&#xff0c;这篇博文就说说asp.net web api演进时的版本管理。asp.net web api的版本管理是通过微软的一个包来实现的。Install-Package Microsoft.AspNetCore.Mvc.Versioning通过url参数: api/order/api-versi…

初二物理模型有哪些_初二是成绩下滑的高危期,做好这5点成绩涨涨涨!(附全学科提升技巧,家长转给孩子!)...

原标题&#xff1a;初二是成绩下滑的高危期&#xff0c;做好这5点成绩涨涨涨&#xff01;(附全学科提升技巧&#xff0c;家长转给孩子&#xff01;)又到了每周五【学习经验分享】的时候了。今天小于老师分享的是初二关键时期可能会出现的问题&#xff0c;以及全科提升技巧。我们…

14个你可能不知道的JavaScript调试技巧

以更快的速度和更高的效率来调试JavaScript 熟悉工具可以让工具在工作中发挥出更大的作用。尽管江湖传言 JavaScript 很难调试&#xff0c;但如果你掌握了几个技巧&#xff0c;就能用很少的时间来解决错误和bug。 文中已经列出了14个你可能不知道的调试技巧&#xff0c;但是可…

mysql校对规则_MYSQL校对规则

一、前言有时候遇到这种情况&#xff0c;你用一个like语句查询&#xff0c;查到的结果中有一些并没有包含你查询的关键词的纪录&#xff1b;有时候遇到这种情况&#xff0c;你的数据库自作聪明的大小写不敏感&#xff0c;让你在更新时把大小写不同的两条记录都更新了&#xff1…

基于NHibernate的留言本

留言本环境&#xff1a;access2003 vs2005 整个留言本的类视图&#xff1a; 1.新建一个空的解决方案 NHibernateMessage 依次建立项目Model,DAL,BLL,Command四个项目 2.Model项目处理 删除自动生成的class1.cs文件&#xff0c;新建message.cs文件其代码如下 Codeusing System;…

腾讯招.NET要求以下几点,你准备好了吗?

今天是大年初七&#xff0c;上班第一天&#xff0c;你在关注什么&#xff1f;2021年跳槽季可能是近10年来最火爆的跳槽季&#xff0c;各HR都在摩拳擦掌&#xff0c;新的征程已开始&#xff0c;.NET开发者们&#xff0c;也该行动起来了&#xff01;上图是腾讯的.NET Core招聘标准…

不得了,日本出版社竟是这样吸引死宅学编程的

此前日本出版社“翔泳社”推出 IT 专业用语拟人化的 IT 说明书&#xff0c;将书中相关名词用萌妹子来表现&#xff0c;并对其性格等方面进行了设定。 比如 HTTP 酱由于在互联网上应用最为广泛&#xff0c;经常与大家见面&#xff0c;因此被设计成了偶像。她与其它协议有着很好的…

mysql表空间权限_MySQL InnoDB表空间加密示例详解

前言从 MySQL5.7.11开始&#xff0c;MySQL对InnoDB支持存储在单独表空间中的表的数据加密 。此功能为物理表空间数据文件提供静态加密。该加密是在引擎内部数据页级别的加密手段&#xff0c;在数据页写入文件系统时加密&#xff0c;加密用的是AES算法&#xff0c;而其解密是在从…

Dapr 正式发布 1.0

年前我写了一篇博客《Dapr 已在塔架就位 将发射新一代微服务》&#xff0c; 今天Dapr 正式发布了1.0 &#xff1a;Dapr Runtime v1.0.0Dapr dotnet SDK v1.0.0随着Dapr 发布1.0 版本&#xff0c; .NET团队编写的《Dapr for .NET Developers》&#xff1a;https://github.com/do…

100 万在中国不同地方能活多久?

最近&#xff0c;一张名为 “100 万在中国各省能生活多久&#xff1f;” 的图片在网上流传 话不多说&#xff0c;往下看 没错&#xff0c;就是正如你们看到的 天朝大北京 以“100万能活19年9个月”的 成绩排名“倒数第一” 图片一出 数据君虎口一震 顿时一声惊叫 统计按“年人均…

重磅:.NET 6 发布首个预览版

前言2021 年 2 月 17 日微软发布了 .NET 6 的 Preview 1 版本&#xff0c;那么来看看都有什么新特性和改进吧&#xff0c;由于内容太多了因此只介绍一些较为重点的项目。ASP.NET Core 6 Preview 1 和 EF Core 6 Preview 1 同样有很多的更新内容&#xff0c;但是限于篇幅就不在这…