【Mybatis用法】Mybatis 高级结果映射,ResultMap Association,mybatis的一对多,多对一,以及多对多的配置和使用

简介: 【Mybatis用法】Mybatis 高级结果映射,ResultMap Association,mybatis的一对多,多对一,以及多对多的配置和使用

一、背景描述

需求:查询任务逾期记录时,把任务相关信息查询出来;

表设计:任务相关信息是一张表(uoa_assignment),任务逾期记录是一张表(uoa_assignment_overdue_log);外键是任务主键(id);

JavaBean:class Assignment, class AssignmentOverdueLog; class AssignmentOverdueLog中包含class Assignment对象。

目的:在查询任务逾期记录时,两张表关联查询出来之后,想要把Assignment的结果集映射到AssignmentOverdueLog中。

两个JavaBean对象如下:AssignmentOverdueLog对象中包含一个Assignment对象。

在查询任务逾期记录时,两张表关联查询出来之后,想要把Assignment的结果集映射到AssignmentOverdueLog中。

二、解决方案

mapper.xml中正确的写法

方法1

写两个<resultMap></resultMap>,通过<association>标签关联起来,然后在查询的sql语句结果集映射中填写外层的<resultMap>的属性id。

在上面的例子中,您会看到AssignmentOverdueLog联合一个“assignmentResultMap”结果映射来加载Assignment实例。

重点提示:id元素在嵌套结果映射中扮演了非常重要的角色,您应该总是指定一个或多个属性来唯一标识这个结果集。事实上,如果您没有那样做,MyBatis也会工作,但是会导致严重性能开销。选择尽量少的属性来唯一标识结果,而使用主键是最明显的选择(即使是复合主键)。

上面的例子使用一个扩展的resultMap 元素来联合映射。这可使Assignment结果映射可重复使用

然后,如果您不需要重用它,您可以直接嵌套这个联合结果映射。这就是另外一种写法了。

方法2

方法3

上面的例子,首先执行<select id=“queryListByLastMonth”>,执行结果存放到<resultMap id=“assignmentOverdueLogMap”>结果映射中。“assignmentOverdueLogMap”是一个AssignmentOverdueLog类型,从<select id=“queryListByLastMonth”>查出的数据都会自动赋值给”assignmentOverdueLogMap”的与列名匹配的属性,这时assignment_id,responsibleUser,responsibleName等就被赋值了。同时“assignmentOverdueLogMap”还有一个关联属性"assignment",执行嵌套查询select=”getAssignment”后,Assignment对象的属性id,type,transactType,title,description等也被赋于数据库中匹配的值。

我们使用两个select语句:一个用来加载AssignmentOverdueLog,另一个用来加载Assignment。AssignmentOverdueLog的resultMap 描述了使用“getAssignment”语句来加载Assignment的属性。

如果列名和属性名称相匹配的话,所有匹配的属性都会自动加载。

虽然这个方法简单,但是对于大数据集或列表查询,就非常不友好了。此问题被称为“N+1 选择问题”(N+1 Selects Problem)。概括地说,N+1选择问题是这样产生的:

1、您执行单条SQL语句去获取一个列表的记录( “+1”)。

2、对列表中的每一条记录,再执行一个联合select 语句来加载每条记录更加详细的信息(“N”)。

这个问题会导致成千上万的SQL语句的执行,因此并非总是可取的。

上面的例子,MyBatis可以使用延迟加载这些查询,因此这些查询立马可节省开销。然而,如果您加载一个列表后立即迭代访问嵌套的数据,这将会调用所有的延迟加载,因此性能会变得非常糟糕。

鉴于此,这有另外一种方式。联合嵌套结果集(Nested Results for Association),也就是上面的方法1和方法2两种方式。

会用到ResultMap联合嵌套结果集(Nested Results for Association)

ResultMap 一个可以映射联合嵌套结果集到一个适合的对象视图上的ResultMap 。这是一个替代的方式去调用另一个select 语句。它允许您去联合多个表到一个结果集里。这样的结果集可能包括冗余的、重复的需要分解和正确映射到一个嵌套对象视图的数据组。简言之,MyBatis 让您把结果映射‘链接’到一起,用来处理嵌套结果。也就是上面的方法1和方法2两种方式。

 

在上面的例子中您已经看到如果处理“一对一”(“has one”)类型的联合查询。但是对于“一对多”(“has many”)的情况如果处理呢?这个问题在下一节讨论:(待补充........)。

 

 

 

拓展:

<association property="assignment" javaType="com.iot.uoa.assignment.entity.Assignment">
  <result property="id" column="id"/>
  <result property="type" column="task_type"/>
  <result property="title" column="title"/>
  <result property="responsibleUser" column="responsible_user"/>
  <result property="responsibleName" column="responsible_name"/>
  <result property="transactType" column="transact_type"/>
  <result property="description" column="description"/>
  <result property="taskLevel" column="task_level"/>
</association>

Association元素处理“has-one”(一对一)这种类型关系。比如在我们的例子中,一个AssignmentOverdueLog有一个Assignment。联合映射与其它的结果集映射工作方式差不多,指定property、column、javaType(通常MyBatis会自动识别)、jdbcType(如果需要)、typeHandler。

不同的地方是您需要告诉MyBatis 如何加载一个联合查询。MyBatis使用两种方式来加载:

Select:通过执行另一个返回预期复杂类型的映射SQL语句(即引用外部定义好的SQL语句块)。

Results:通过嵌套结果映射(nested result mappings)来处理联接结果集(joined results)的重复子集。

首先,让我们检查一下元素属性。正如您看到的,它不同于普通只有selectresultMap属性的结果映射。

属性 描述
property 映射数据库列的字段或属性。如果JavaBean 的属性与给定的名称匹配,就会使用匹配的名字。否则,MyBatis 将搜索给定名称的字段。两种情况下您都可以使用逗点的属性形式。比如,您可以映射到”username”,也可以映射到更复杂点的”address.street.number”。
column

数据库的列名或者列标签别名。与传递给resultSet.getString(columnName)的参数名称相同。

注意: 在处理组合键时,您可以使用column= “{prop1=col1,prop2=col2}”这样的语法,设置多个列名传入到嵌套查询语句。这就会把prop1和prop2设置到目标嵌套选择语句的参数对象中。

javaType 完整java类名或别名(参考上面的内置别名列表)。如果映射到一个JavaBean,那MyBatis 通常会自行检测到。然而,如果映射到一个HashMap,那您应该明确指定javaType 来确保所需行为。
jdbcType 支持的JDBC类型列表中列出的JDBC类型。这个属性只在insert,update 或delete 的时候针对允许空的列有用。JDBC 需要这项,但MyBatis 不需要。如果您直接编写JDBC代码,在允许为空值的情况下需要指定这个类型。
typeHandler 我们已经在文档中讨论过默认类型处理器。使用这个属性可以重写默认类型处理器。它的值可以是一个TypeHandler实现的完整类名,也可以是一个类型别名。

显示详细信息

联合嵌套选择(Nested Select for Association)

select 通过这个属性,通过ID引用另一个加载复杂类型的映射语句。从指定列属性中返回的值,将作为参数设置给目标select 语句。表格下方将有一个例子。注意:在处理组合键时,您可以使用column=”{prop1=col1,prop2=col2}”这样的语法,设置多个列名传入到嵌套语句。这就会把prop1和prop2设置到目标嵌套语句的参数对象中。

 

 

 

完结!

 

相关文章
|
12天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
2月前
|
SQL XML Java
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
文章介绍了MyBatis中动态SQL的用法,包括if、choose、where、set和trim标签,以及foreach标签的详细使用。通过实际代码示例,展示了如何根据条件动态构建查询、更新和批量插入操作的SQL语句。
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
|
2月前
|
SQL XML Java
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
文章介绍了MyBatis中高级查询的一对多和多对一映射处理,包括创建数据库表、抽象对应的实体类、使用resultMap中的association和collection标签进行映射处理,以及如何实现级联查询和分步查询。此外,还补充了延迟加载的设置和用法。
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
|
2月前
|
SQL XML Java
mybatis复习01,简单配置让mybatis跑起来
文章介绍了MyBatis的基本概念、历史和特点,并详细指导了如何配置MyBatis环境,包括创建Maven项目、添加依赖、编写核心配置文件、创建数据表和实体类、编写Mapper接口和XML配置文件,以及如何编写工具类和测试用例。
mybatis复习01,简单配置让mybatis跑起来
|
1月前
|
SQL XML Java
Mybatis的<where>,<if>等标签用法
这篇文章详细解释了Mybatis中<where>和<if>等标签的用法,展示了如何在SQL动态构建中有效地过滤条件和处理逻辑分支。
167 1
|
1月前
|
SQL Java 数据库连接
Mybatis的<insert>,<update>,<delete>标签用法
这篇文章详细讲解了Mybatis中<insert>, <update>, <delete>标签的使用方法,并提供了示例代码来展示如何执行数据库的增删改操作。
27 0
|
2月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
44 1
|
1月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
105 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
1月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
52 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
1月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
288 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个