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

本文目录

一、背景描述

二、解决方案

方法1

方法2

方法3


一、背景描述

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

表设计:任务相关信息是一张表(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设置到目标嵌套语句的参数对象中。

 

 

 

完结!

 

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
MyBatis 中进行一对多映射时,可以使用嵌套查询或嵌套结果映射来完成。下面是具体的实现方法: 1. 嵌套查询 嵌套查询是指在主查询中使用子查询来获取从表的数据,然后将这些数据与主表数据合并返回。这种方式需要在 SQL 语句中使用嵌套查询语句,例如: ``` <select id="selectUser" resultType="User"> select * from user where id=#{id}; select * from order where user_id=#{id}; </select> ``` 这样就能同时查询出用户信息和该用户的所有订单信息。在使用时,可以将多条 SQL 语句封装到一个 Mapper 接口中,并在 XML 配置文件中进行配置。 2. 嵌套结果映射 嵌套结果映射是指在主查询的结果集中包含从表的数据,然后使用 MyBatisresultMap 映射方式进行映射。这种方式需要在 XML 配置文件中定义 resultMap,并使用 collection 元素来定义从表的映射关系,例如: ``` <resultMap id="userMap" type="User"> <id property="id" column="id"/> <result property="name" column="name"/> <collection property="orders" ofType="Order"> <id property="id" column="order_id"/> <result property="price" column="price"/> </collection> </resultMap> ``` 这样就能同时查询出用户信息和该用户的所有订单信息,并将其映射到 User 对象中。在使用时,只需要在 SQL 语句中使用 JOIN 或 LEFT JOIN 连接主表和从表即可。 总之,MyBatis 中进行一对多映射可以使用嵌套查询或嵌套结果映射来完成,具体的实现方式需要根据具体的场景和需求来选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

No8g攻城狮

向每一个努力改变现状的你致敬!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值