前言

上一篇博客中针对一对一映射做了一个简单的总结,但是针对嵌套查询中的fetchType属性却没有做过多的阐述,一对多模式其实和一对一模式大同小异,只是使用的标签不同,同时也会涉及到fetchType的使用,这篇博客中会统一进行总结。

collection标签

和association标签类似,总体来说collection标签的使用分为两种方式。
一种是嵌套的结果查询——一次SQL查询将所有的结果查询出来,然后通过配置的结果映射,将数据映射到不同的对象中。
第二种是集合的嵌套查询——并不是一次SQL查询出所有结果,根据上一次查询的结果,作为参数传递给下一层的SQL,通过多次查询完成结果(可能有点晕,后面看实例)。
具体的实例还是会用老生常谈的RBAC权限模型:一个用户拥有多个角色,一个角色拥有多个权限。

在实例开始之前,需要构建相关属性维持一对多的关系。
SysUser中增加List<SysRole> roleList属性。

    private List<SysRole> roleList;public List<SysRole> getRoleList() {return roleList;}public void setRoleList(List<SysRole> roleList) {this.roleList = roleList;}

SysRole中增加List<SysPrivilege> privilegeList属性

    private List<SysPrivilege> privilegeList;public List<SysPrivilege> getPrivilegeList() {return privilegeList;}public void setPrivilegeList(List<SysPrivilege> privilegeList) {this.privilegeList = privilegeList;}

嵌套结果映射

在相关实体类中完成了属性的配置,我们需要做的就是将结果映射到这些属性上。这个时候collection标签的作用就开始了
1、初步版本,所有的属性映射都在一起

    <resultMap id="userRoleListMap" type="com.learn.chapter06one2many.domain.SysUser"><id property="id" column="id"></id><result property="userPassword" column="user_password"></id><result property="userName" column="user_name"></result><result property="userEmail" column="user_email"></result><result property="userInfo" column="user_info"></result><result property="headImg" column="head_img" jdbcType="BLOB"></result><result property="createTime" column="create_time" jdbcType="TIMESTAMP"></result><collection property="roleList" columnPrefix="role_" ofType="com.learn.chapter06one2many.domain.SysRole"><id property="id" column="id"></id><result property="roleName" column="role_name"></result><result property="enabled" column="enabled"></result><result property="createBy" column="create_by"></result><result property="createTime" column="create_time" jdbcType="TIMESTAMP"></result></collection></resultMap>

可以看到collection其实和association差不多,collection支持的属性作用和association完全相同

2、直接应用RoleMapper中的映射
将上述简单版本中的collection修改如下即可

<collection property="roleList" columnPrefix="role_" resultMap="com.learn.chapter06one2many.dao.RoleMapper.roleMap"></collection>

上述执行的查询情况

可以看到一次执行的查询查找出三个结果,但是针对MyBatis将其中的两条查询结果融入到了第一条,这个就和MyBatis处理的规则有关系了。

3、将权限表也进行关联

    <resultMap id="privilegeMap" type="com.learn.chapter06one2many.domain.SysPrivilege"><id property="id" column="id"></id><result column="privilege_name" property="privilegeName"></result><result column="privilege_url" property="privilegeUrl"></result></resultMap>

RoleMapper中增加相关映射

    <resultMap id="rolePrivilegeListMap" extends="roleMap" type="com.learn.chapter06one2many.domain.SysRole"><collection property="privilegeList" columnPrefix="privilege_" resultMap="com.learn.chapter06one2many.dao.PrivilegeMapper.privilegeMap"></collection></resultMap>

userMapper增加相关映射

    <!--加入了Privilege--><resultMap id="userRoleListMapPrivilege" type="com.learn.chapter06one2many.domain.SysUser"><id property="id" column="id"></id><result property="userPassword" column="user_password"></result><result property="userName" column="user_name"></result><result property="userEmail" column="user_email"></result><result property="userInfo" column="user_info"></result><result property="headImg" column="head_img" jdbcType="BLOB"></result><result property="createTime" column="create_time" jdbcType="TIMESTAMP"></result><!--使用RoleMapper本身的映射--><collection property="roleList" columnPrefix="role_" resultMap="com.learn.chapter06one2many.dao.RoleMapper.rolePrivilegeListMap"></collection></resultMap>

增加相关SQL

    <select id="selectAllUserAndRolesAndPrivileges" resultMap="userRoleListMapPrivilege">selectu.id,u.user_name,u.user_password,u.user_email,u.user_info,u.head_img,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,p.id role_privilege_id,p.privilege_name role_privilege_privilege_name,p.privilege_url role_privilege_privilege_urlfrom sys_user uinner join sys_user_role ur on u.id = ur.user_idinner join sys_role r on ur.role_id = r.idinner join sys_role_privilege rp on rp.role_id = r.idinner join sys_privilege p on p.id = rp.privilege_id;</select>

需要注意的是sys_privilege表中列的列名,都变成了role_privilege_,在嵌套中前缀属性的配置也要一层层加上,这个需要注意

最终执行结果:

嵌套结果映射的结果处理规则

MyBatis在处理结果的时候,会判断结果是否相同,如果是相同的就只会保留一个结果,映射结果的处理,核心就是MyBatis如何判断结果是相同的。这个时候<id>标签的作用就显现出来了。

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

id除了标记主键之外,如果配置了这个id属性,MyBatis只需要逐条比较所有数据中id标签配置的字段值是否相同即可。如果两条数据的id部分相同,就会标记属于同一个用户,并会将这个数据合并到同一个用户中。

简单修改:

    <resultMap id="userRoleListMap" type="com.learn.chapter06one2many.domain.SysUser"><!--<id property="id" column="id"></id>--><id property="userPassword" column="user_password"></id><result column="id" property="id"></result><result property="userName" column="user_name"></result><result property="userEmail" column="user_email"></result><result property="userInfo" column="user_info"></result><result property="headImg" column="head_img" jdbcType="BLOB"></result><result property="createTime" column="create_time" jdbcType="TIMESTAMP"></result><!--使用RoleMapper本身的映射--><collection property="roleList" columnPrefix="role_" resultMap="com.learn.chapter06one2many.dao.RoleMapper.roleMap"></collection></resultMap>

将id对应的属性改成了userPassword,之后在数据库中将所有的password数据修改成123456,执行查询会发现如下结果:

MyBatis只会判断password字段,如果相同就会被判断成同一条数据,数据库中password字段都是一致的,所以最后的结果也就只有一条。

如果没有配置id属性MyBatis会逐条属性判断,如果有一个属性值不同,则会判断为不同,当字段数为M,查询结果有N条时,就需要进行M*N次比较,相比配置了id属性,只需要比较N次,效率会大打折扣。因此要尽量配置id标签。

嵌套查询

其实通俗点将,嵌套查询就是利用简单的SQL查询,通过多次查询转换为我们需要的结果。

1、PrivilegeMapper中配置简单映射

    <select id="selectPrivilegeByRoleId" resultMap="privilegeMap">select p.*from sys_privilege pinner join sys_role_privilege rp on rp.privilege_id = p.idwhere role_id = #{roleId}</select>

2、RoleMapper中配置映射和对应的查询方法

    <resultMap id="rolePrivilegeListMapSelect" extends="roleMap" type="com.learn.chapter06one2many.domain.SysRole"><collection property="privilegeList" fetchType="lazy" column="{roleId=id}" select="com.learn.chapter06one2many.dao.PrivilegeMapper.selectPrivilegeByRoleId"></collection></resultMap>
    <select id="selectRoleByUserId" resultMap="rolePrivilegeListMapSelect">selectr.id,r.role_name,r.enabled,r.create_by,r.create_timefrom sys_role rinner join sys_user_role ur on ur.role_id = r.idwhere ur.user_id = #{userId}</select>

3、UserMapper中配置映射和查询

    <resultMap id="usereRoleListMapSelect" extends="BaseResultMap" type="com.learn.chapter06one2many.domain.SysUser"><collection property="roleList" fetchType="lazy" select="com.learn.chapter06one2many.dao.RoleMapper.selectRoleByUserId" column="{userId=id}"></collection></resultMap>
    <select id="selectAllUserAndRolesSelect" resultMap = "usereRoleListMapSelect">selectu.id,u.user_name,u.user_password,u.user_email,u.user_info,u.head_img,u.create_timefrom sys_user uwhere u.id = #{id}</select>

这里相关属性fetchType的配置,后期再详细加入,除此之外还有aggressLazyLoading属性,以及与配置加载方法相关的LazyLoadTiggerMethods属性,这些后期会做一个博客单独整理。

最终执行结果:

总结

梳理了一对多的相关使用方式,但是针对fetchType等相关简单查询的语句,这里依旧没有进一步总结,后续针对这一类属性单独梳理。

MyBatis学习笔记(六)——高级查询之一对多映射相关推荐

  1. MySQL学习笔记-03高级查询、多表联合查询、聚合函数、子查询、视图、存储过程、权限、

    关于作者 金山老师:从事Java.大数据.Python职业化培训6年,项目管理.软件开发14年.欢迎添加我的微信号[jshand],最近建了一些微信交流群,扫描下方二维码添加公众号,回复:进群 文章目 ...

  2. 原始dao和Mapper动态代理的开放方式---Mybatis学习笔记(六)

    1.原始Dao开发方式 原始Dao开发方法需要程序员编写Dao接口和Dao实现类. 1.映射文件:(user.xml) <?xml version="1.0" encodin ...

  3. Mybatis学习笔记6 模糊查询like

    1.模糊 like 模糊查询的实现有两种方式, 一是java代码中给查询数据加上"%"; 二是在mapper文件sql语句的条件位置加上"%". 需求:查询姓名 ...

  4. mysql的sqlyog学习笔记(高级查询部分)(代码用命令行显示 )

    索引 分组查询 简单分组 可以实现分组前的筛选 可以实现分组后的筛选 可以实现排序 按多个字段分组 连接查询(SQL99语法) 内连接 语法: 等值连接 简单查询 添加筛选条件 添加分组+筛选 添加分 ...

  5. mybatis学习笔记(12)-多对多查询

    mybatis学习笔记12-多对多查询 示例 多对多查询总结 resultMap总结 本文实现多对多查询,查询用户及用户购买商品信息. 示例 查询主表是:用户表 关联表:由于用户和商品没有直接关联,通 ...

  6. mybatis学习笔记(13)-延迟加载

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(13)-延迟加载 标签: mybatis [TOC] resultMap可以实现高级映射(使用asso ...

  7. 【应用篇】MyBatis学习笔记

    MyBatis学习笔记 一 环境配置 1 什么是MyBatis? ​ MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的 JDBC 代码和参 ...

  8. MyBatis学习笔记(1)—使用篇

    MyBatis学习笔记(1)-使用篇 MyBatis学习笔记(2)-映射关系篇 MyBatis学习笔记(3)-高级映射之一对一映射 Mybatis学习笔记(4)-高级映射之一对多映射 Mybatis学 ...

  9. mybatis学习笔记(7)-输出映射

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(7)-输出映射 标签: mybatis [TOC] 本文主要讲解mybatis的输出映射. 输出映射有 ...

  10. MyBatis多参数传递之Map方式示例——MyBatis学习笔记之十三

    前面的文章介绍了MyBatis多参数传递的注解.参数默认命名等方式,今天介绍Map的方式.仍然以前面的分页查询教师信息的方法findTeacherByPage为例(示例源代码下载地址:http://d ...

最新文章

  1. matlab实战中一些重要的函数总结
  2. 怎么区分IP和MAC?子网掩码有何作用?—Vecloud微云
  3. unity 实现文本选中_Unity中如何读取TXT文本内容
  4. [EF Core]数据迁移(二)
  5. 二叉树前序、中序、后序遍历求法
  6. PCV相关指标控制要求
  7. 【渝粤教育】21秋期末考试管理学原理★10013k1
  8. ExtJS-3.4.0系列目录
  9. leetcode——Divide Two Integers
  10. idea 新建的java项目没发run_IntelliJ IDEA 如何创建一个普通的java项目,及创建java文件并运行...
  11. 如何运用Python与高德API来获取餐饮、珠宝等线下行业的竞争对手信息?
  12. Maven相关jar包安装
  13. 2022年上半年系统集成项目管理工程师上午真题及答案解析
  14. matlab如何求状态方程,matlab状态方程解
  15. Office 文档在线预览解决方案
  16. 101条计算机经典名言(英汉对照版)
  17. 微信小程序初始界面设置密码
  18. Android录制声音文件(音频),并播放
  19. 基于C++实现两个分数的加减法
  20. mybatis源码过程学习梳理

热门文章

  1. 全卷积神经网络(FCN)
  2. 两个简单方法--shift()和unshift();
  3. J9数字论:区块链+DAO3:去中心化的互联网世界
  4. Activiti7工作流介绍及使用
  5. 使用HBuilder开发移动APP
  6. AR502H-CN开发笔记18:快速建立开发环境
  7. git之pull与push
  8. RAD Studio 10.4 for delphi XE Assigned和Nil的联系与区别
  9. matlab 群延迟,实现最小相位群延迟的音节切分算法的一些问题
  10. 如何对图像进行卷积操作