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 批量添加数据的两种实现方式
做开发的这几年期间经常遇到类似处理这种形式数据的问题,也遇到很多刚刚入行的新同学,发现他们做处理这块,经验不够,今天特地整理了一下,大家都会遇到的几种情况,代码也都粘贴出来了,拿去不谢,有时间大家还是 ...
- Mybatis系列全解(七):全息视角看Dao层两种实现方式之传统方式与代理方式
封面:洛小汐 作者:潘潘 一直以来 他们都说为了生活 便追求所谓成功 顶级薪水.名牌包包 还有学区房 · 不过 总有人丢了生活 仍一无所获 · 我比较随遇而安 有些事懒得明白 平日里问心无愧 感兴趣的 ...
- mybatis中批量插入的两种方式(高效插入)
MyBatis简介 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用 ...
- MyBatis开发Dao层的两种方式(原始Dao层开发)
本文将介绍使用框架mybatis开发原始Dao层来对一个对数据库进行增删改查的案例. Mapper动态代理开发Dao层请阅读我的下一篇博客:MyBatis开发Dao层的两种方式(Mapper动态代理方 ...
- MyBatis开发Dao层的两种方式(Mapper动态代理方式)
MyBatis开发原始Dao层请阅读我的上一篇博客:MyBatis开发Dao层的两种方式(原始Dao层开发) 接上一篇博客继续介绍MyBatis开发Dao层的第二种方式:Mapper动态代理方式 Ma ...
- 设置Mybatis打印调试sql的两种方式
http://blog.csdn.net/gao36951/article/details/53641432 ********************************************* ...
- Spring学习之Spring与Mybatis的两种整合方式
本机使用IDEA 2020.1.MySql 8.0.19,通过Maven进行构建 环境准备 导入maven依赖包 <dependencies> <dependency> < ...
- 第一章 Mybtais的两种启动方式
Mybatis的两种启动方式如下: 1.xml实现: xml的实现方式中,主要是通过手动创建SqlSession,然后调用session.selectOne()方法实现来实现. 首先是创建Config ...
- 细说java中Map的两种迭代方式
曾经对java中迭代方式总是迷迷糊糊的,今天总算弄懂了.特意的总结了一下.基本是算是理解透彻了. 1.再说Map之前先说下Iterator: Iterator主要用于遍历(即迭代訪问)Collecti ...
随机推荐
- React 之React.createContext
使用Context,可以跨越组件进行数据传递 import React from 'react'; import ReactDOM from 'react-dom'; const ThemeConte ...
- Codeforces 864E - Fire(dp)
原题连接:http://codeforces.com/problemset/problem/864/E 题意:一个人想从大火中带走一些东西.每次他只能带一个,耗时ti ,价值为pi, 当总时间超过di ...
- 搭建 .Net RabbitMQ 开发环境
开发环境,window 10 64位,VS2017,系统账号需要用administrator. 1 先需要安装erlang语言开发包,一路默认安装就是了,地址:http://www.erlang.or ...
- c++ bitset——一个有趣的类型
转自:https://www.cnblogs.com/magisk/p/8809922.html 概况:一个最小可达1bit的特殊数据结构
- 阿里云CentOS 7.3安装Redis详细步骤
############ 准备 ############### 从Redis官网下载Linux redis3.2.6版本,我下载的redis-3.2.6.tar.gz(目前最新稳定版),下载到/u ...
- android中各种组件的生命周期问题
1,activiy生命周期 http://www.ibm.com/developerworks/cn/opensource/os-cn-android-actvt/ 结合ativity的状态转换来看才 ...
- python大佬养成计划----HTML DOM
什么是DOM? DOM (Document Object Model) 译为文档对象模型,是 HTML 和 XML 文档的编程接口.HTML DOM 定义了访问和操作 HTML 文档的标准方法.DOM ...
- Bash is an sh-compatible command language interpreter that executes commands read from the standard input or from a file.
w https://linux.die.net/man/1/bash bash - GNU Bourne-Again SHell Description Bash is an sh-compatibl ...
- 【cs231n作业笔记】二:SVM分类器
可以参考:cs231n assignment1 SVM 完整代码 231n作业 多类 SVM 的损失函数及其梯度计算(最好)https://blog.csdn.net/NODIECANFLY/ar ...
- 在mpvue或者Vue中使用VUEX
第一个页面Index,主页哦 import Vue from'vue' import Vuex from'vuex' import getters from'./getters' import sta ...