mybatis resultMap之collection聚集两种实现方式

 更新时间:2024年09月04日 08:36:19   作者:gmHappy  
本文主要介绍了mybatis resultMap之collection聚集两种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

最近做得项目用到了MyBatis处理一对多的映射关系,下面的两个方法中用到了集合的嵌套查询方法,下面仔细学习一下这两种方式

聚集元素用来处理“一对多”的关系。需要指定映射的Java实体类的属性,属性的javaType(一般为ArrayList);列表中对象的类型ofType(Java实体类);对应的数据库表的列名称;
不同情况需要告诉MyBatis 如何加载一个聚集。MyBatis 可以用两种方式加载:

  • select: 执行一个其它映射的SQL 语句返回一个Java实体类型。较灵活但会将执行多次嵌套的SQL语句。

  • resultMap: 使用一个嵌套的结果映射来处理通过join查询结果集,映射成Java实体类型。

两种加载方式格式如下:

集合的嵌套查询(select)

<collection property="Java属性名" ofType="另一Java类名" javaType="ArrayList" column="关联主键ID(用于嵌套查询SQL语句传入参数,多个用逗号分开)" select="另一个select映射SQL的ID"/>

<select parameterType="int" resultType="另一Java类名" id="另一个select映射SQL的ID">
	SQL语句
</select>
<resultMap id="blogResult" type="Blog">  
	<collection property="posts" javaType=”ArrayList” column="blog_id" ofType="Post" select="selectPostsForBlog"/>  
</resultMap>  
   
<select id="selectBlog" parameterType="int" resultMap="blogResult">  
	SELECT * FROM BLOG WHERE ID = #{id}  
</select>  
   
<select id="selectPostsForBlog" parameterType="int" resultType="Author">  
	SELECT * FROM POST WHERE BLOG_ID = #{id}  
</select>

注意:column属性的值必须与相应的SQL查询语句中的列名相同。MyBatis会将第一条SQL语句查询出来的该列的值用于所聚集的SQL映射语句的入参。因第一条SQL语句查询出来的每个该列的值都将用于执行另一个SQL语句,所以聚集的SQL语句将被多次执行

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

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

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

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

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

鉴于此,这有另外一种方式。

集合的嵌套结果集(Nested Results for Collection)

<resultMap id="resultMap的ID"  type="Java类名">
	<collection property="Java属性名" ofType="另一Java类名" javaType="ArrayList" resultMap="另一resultMap的ID"/>
</resultMap>
  
<resultMap="另一resultMap的ID" type="另一Java类名">
	<id property="id" column="关联主键ID"/>
	....
</resultMap>
<select id="selectBlog" parameterType="int" resultMap="blogResult">  
	select  
		B.id as blog_id,  
		B.title as blog_title,  
		B.author_id as blog_author_id,  
		P.id as post_id,  
		P.subject as post_subject,  
		P.body as post_body,  
	from Blog B  
	left outer join Post P on B.id = P.blog_id  
	where B.id = #{id}  
</select>

同样,我们把Blog和Post两张表连接在一起,并且也保证列标签名在映射的时候是唯一且无歧义的。现在将Blog和Post的集合映射在一起是多么简单:

<resultMap id="blogResult" type="Blog">  
	<id property="id" column="blog_id" />  
	<result property="title" column="blog_title"/>  
	<collection property="posts" ofType="Post">  
		<id property="id" column="post_id"/>  
		<result property="subject" column="post_subject"/>  
		<result property="body" column="post_body"/>  
	</collection>  
</resultMap>  

再次强调一下,id 元素是非常重要的。
如果希望结果映射有更好的可重用性,您可以使用下面的方式:

<resultMap id="blogResult" type="Blog">  
	<id property="id" column="blog_id" />  
	<result property="title" column="blog_title"/>  
	<collection property="posts" ofType="Post" resultMap="blogPostResult"/>  
</resultMap>  
   
<resultMap id="blogPostResult" type="Post">  
	<id property="id" column="post_id"/>  
	<result property="subject" column="post_subject"/>  
	<result property="body" column="post_body"/>  
</resultMap>  

注意:column属性的值必须与相应的SQL查询语句的列名一样。

到此这篇关于mybatis resultMap之collection聚集两种实现方式的文章就介绍到这了,更多相关mybatis resultMap collection聚集内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot实现隐式参数注入的完整指南

    SpringBoot实现隐式参数注入的完整指南

    这篇文章主要为大家详细介绍了SpringBoot实现隐式参数注入的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-11-11
  • SpringBoot 装饰器@TableField原理解析

    SpringBoot 装饰器@TableField原理解析

    本文解析了MyBatis-Plus的@TableField注解,用于非主键字段与数据库列的映射及行为控制,涵盖自动填充、乐观锁、多租户等企业级功能,提供使用技巧、常见问题及示例代码,感兴趣的朋友跟随小编一起看看吧
    2025-09-09
  • 关于MyBatis plus条件构造器的逐条详解

    关于MyBatis plus条件构造器的逐条详解

    什么是条件构造器呢?简单来说,条件构造器就是用来生成我们查数据库的sql。它可以简化sql代码的编写,灵活、方便且易于维护
    2021-09-09
  • Java8的Lambda和排序

    Java8的Lambda和排序

    这篇文章主要介绍了Java8的Lambda和排序,对数组和集合进行排序是Java 8 lambda令人惊奇的一个应用,我们可以实现一个Comparators来实现各种排序,下面文章将有案例详细说明,想要了解得小伙伴可以参考一下
    2021-11-11
  • Linux系统Docker拉取JDK21镜像超细详解

    Linux系统Docker拉取JDK21镜像超细详解

    这篇文章主要介绍了如何在Linux系统上使用Docker拉取JDK21镜像,并基于该镜像搭建开发和测试环境,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2024-12-12
  • Spring 中@Autowired、@Resource、@Inject 注解实现原理使用案例详解

    Spring 中@Autowired、@Resource、@Inject 注解实现原理使用案例详解

    这篇文章主要介绍了Spring 中@Autowired、@Resource、@Inject 注解实现原理使用案例详解,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2025-04-04
  • Java基础面试题之volatile详解

    Java基础面试题之volatile详解

    Volatile可以看做是轻量级的 Synchronized,它只保证了共享变量的可见性,下面这篇文章主要给大家介绍了关于Java基础面试题之volatile的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • Java inputstream和outputstream使用详解

    Java inputstream和outputstream使用详解

    这篇文章主要介绍了Java inputstream和outputstream使用详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • 使用Java实现将Excel工作表转换为CSV格式

    使用Java实现将Excel工作表转换为CSV格式

    在日常开发中,Excel 文件(.xls/.xlsx)是数据存储和交换的常用格式,本文将介绍如何使用 Spire.XLS for Java 组件,高效实现 Excel 文件到 CSV 格式的转换,需要的可以了解下
    2025-10-10
  • 成功解决IDEA2020 Plugins 连不上、打不开的方法

    成功解决IDEA2020 Plugins 连不上、打不开的方法

    这篇文章主要介绍了成功解决IDEA2020 Plugins 连不上、打不开的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06

最新评论