MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接
表示返回类型的,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在。

1.resultType

在MyBatis进行查询映射的时候,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,
值则是其对应的值。当提供的返回类型属性是resultType的时候,MyBatis会将Map里面的键值对取出赋给
resultType所指定的对象对应的属性。所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,
只是当我们提供的返回类型属性是resultType的时候,MyBatis对自动的给我们把对应的值赋给resultType
所指定对象的属性,而当我们提供的返回类型是resultMap的时候,因为Map不能很好表示领域模型,
我们就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用。

这里要强调的是,Mybatis是对返回的结果的每一行做映射的。所以,下面的语句返回的是Integer,而不是List

Xml代码  
  1. <select id="count" parameterType="AreaDto" resultType="java.lang.Integer">
  2. SELECT id FROM USER
  3. </select>

返回一个int

Xml代码  
  1. <select id="count" parameterType="AreaDto" resultType="java.lang.Integer">
  2. SELECT count(*) FROM USER
  3. </select>

返回map

Xml代码  
  1. <select id=”selectUsers” parameterType=”int” resultType=”hashmap”>
  2. select id, username, hashedPassword
  3. from some_table
  4. where id = #{id}
  5. </select>

这样一个语句简单作用于所有列被自动映射到HashMap的键上,这由resultType属性指定。这在很多情况下是有用的,但是HashMap不能很好描述一个领域模型。那样你的应用程序将会使用JavaBeans或POJOs(Plain Old Java Objects,普通Java对象)来作为领域模型

返回javaBEAN 对象

Xml代码  
  1. <select id="count" parameterType="AreaDto" resultType="User">
  2. SELECT * FROM USER
  3. </select>

要记住类型别名是你的伙伴。使用它们你可以不用输入类的全路径。

Xml代码  
  1. <typeAlias type=”com.someapp.model.User” alias=”User”/>

这些情况下,MyBatis会在幕后自动创建一个ResultMap,基于属性名来映射列到JavaBean的属性上

2.resultMap

MyBatis会自动创建一个ResultMap对象,然后基于查找出来的属性名进行键值对封装,然后再看到返回类型是Blog对象,再从ResultMap中取出与Blog对象对应的键值对进行赋值。

当返回类型直接是一个ResultMap的时候也是非常有用的,这主要用在进行复杂联合查询上,因为进行简单查询是没有什么必要的。

简单resultMap配置

Xml代码  
  1. <resultMap type="com.liulanghan.Blog" id="BlogResult">
  2. <id column="id" property="id"/>
  3. <result column="title" property="title"/>
  4. <result column="content" property="content"/>
  5. <result column="owner" property="owner"/>
  6. </resultMap>
  7. <select id="selectBlog" parameterType="int" resultMap="BlogResult">
  8. select * from t_blog where id = #{id}
  9. </select>

结果集的列比resultMap多会报错么?
不会,只映射resultMap中有的列。

结果集的列比resultMap少会报错么?
不会,只映射结果集中有的列。

高级结果映射

Xml代码  
  1. <resultMap id="detailedBlogResultMap" type="Blog">
  2. <constructor>
  3. <idArg column="blog_id" javaType="int"/>
  4. </constructor>
  5. <result property="title" column="blog_title"/>
  6. <association property="author" column="blog_author_id" javaType=" Author">
  7. <id property="id" column="author_id"/>
  8. <result property="username" column="author_username"/>
  9. <result property="password" column="author_password"/>
  10. <result property="email" column="author_email"/>
  11. <result property="bio" column="author_bio"/>
  12. <result property="favouriteSection" column="author_favourite_section"/>
  13. </association>
  14. <collection property="posts" ofType="Post">
  15. <id property="id" column="post_id"/>
  16. <result property="subject" column="post_subject"/>
  17. <association property="author" column="post_author_id" javaType="Author"/>
  18. <collection property="comments" column="post_id" ofType=" Comment">
  19. <id property="id" column="comment_id"/>
  20. </collection>
  21. <collection property="tags" column="post_id" ofType=" Tag" >
  22. <id property="id" column="tag_id"/>
  23. </collection>
  24. <discriminator javaType="int" column="draft">
  25. <case value="1" resultType="DraftPost"/>
  26. </discriminator>
  27. </collection>
  28. </resultMap>

resultMap
      constructor – 类在实例化时,用来注入结果到构造方法中
           idArg – ID参数;标记结果作为ID可以帮助提高整体效能
           arg – 注入到构造方法的一个普通结果
      id – 一个ID结果;标记结果作为ID可以帮助提高整体效能
      result – 注入到字段或JavaBean属性的普通结果
     association – 一个复杂的类型关联;许多结果将包成这种类型
           嵌入结果映射 – 结果映射自身的关联,或者参考一个
     collection – 复杂类型的集
           嵌入结果映射 – 结果映射自身的集,或者参考一个
    discriminator – 使用结果值来决定使用哪个结果映射
         case – 基于某些值的结果映射
               嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相同的元素,或者它可以参照一个外部的结果映射。

id 和result
   
id和result都映射一个单独列的值到简单数据类型

这两者之间的唯一不同是id表示的结果将是当比较对象实例时用到的标识属性。这帮助来改进整体表现,特别是缓存和嵌入结果映射(也就是联合映射)。

它们共有的属性如下:

property

映射到列结果的字段或属性。如果匹配的是存在的,和给定名称相同的JavaBeans的属性,那么就会使用。否则MyBatis将会寻找给定名称的字段。这两种情形你可以使用通常点式的复杂属性导航。比如,你可以这样映射一些东西:“username”,或者映射到一些复杂的东西:“address.street.number”。

column

从数据库中得到的列名,或者是列名的重命名标签。这也是通常和会传递给resultSet.getString(columnName)方法参数中相同的字符串。

javaType

一个Java类的完全限定名,或一个类型别名(参加上面内建类型别名的列表)。如果你映射到一个JavaBean,MyBatis通常可以断定类型。然而,如果你映射到的是HashMap,那么你应该明确地指定javaType来保证所需的行为。

jdbcType

在这个表格之后的所支持的JDBC类型列表中的类型。JDBC类型是仅仅需要对插入,更新和删除操作可能为空的列进行处理。这是JDBC的需要,而不是MyBatis的。如果你直接使用JDBC编程,你需要指定这个类型-但仅仅对可能为空的值。

typeHandler

我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的类型处理器。这个属性值是类的完全限定名或者是一个类型处理器的实现,或者是类型别名。

constructor

。构造方法注入允许你在初始化时为类设置属性的值,而不用暴露出公有方法。MyBatis也支持私有属性和私有JavaBeans属性来达到这个目的,但是一些人更青睐构造方法注入。

为了向这个构造方法中注入结果,MyBatis需要通过它的参数的类型来标识构造方法。Java没有自查(反射)参数名的方法。所以当创建一个构造方法元素时,保证参数是按顺序排列的,而且数据类型也是确定的。

association

association关联元素处理“有一个”类型的关系,即一对一关联。它有两种关联方式

嵌套查询:通过执行另外一个SQL映射语句来返回预期的复杂类型。

嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。

嵌套查询

Xml代码  
  1. <resultMap  id="userResultMap" type="User">
  2. <id property="id" column="ID" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  3. <result property="loginName" column="LOGIN_NAME" jdbcType="VARCHAR" javaType="java.lang.String"/>
  4. <result property="password" column="password" jdbcType="VARCHAR" javaType="java.lang.String"/>
  5. <result property="roleId" column="role_id" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  6. <association property="role" column="role_id" javaType="Role" select="selectRole"/>
  7. </resultMap>
  8. <select id="selectUser" parameterType="java.lang.Long" resultMap="userResultMap" >
  9. select * from User where id =#{id}
  10. </select>
  11. <select id="selectRole" parameterType="java.lang.Long" resultType="Role" >
  12. select * from Role where id =#{id}
  13. </select>

这里有两个查询,一个查询加载User,一个查询加载Role.
这里select为另外一个映射语句的ID,可以加载这个属性映射需要的复杂类型。获取的在列属性中指定的列的值将被传递给目标select语句作为参数。

注意:
而select 为selectRole的SQL输入参数可以随便给名称,只要是输入参数与压入进去的值类型相同就行了,可以写成:

Xml代码  
  1. select * from Role where id = #{sfffs}

不管输入参数名称是什么,mybatis最终会执行:
效果为:

Sql代码  
  1. select * from role where id =resultSet.getLong("Role_id");

注意:要保证第二个查询查出来的结果只有一条记录。

要处理复合主键,你可以指定多个列名通过column="{prop1=col1,prop2=col2}"这种语法来传递给嵌套查询语句。这会引起prop1和prop2以参数对象形式来设置给目标嵌套查询语句。

Xml代码  
  1. <resultMap  id="userResultMap" type="User">
  2. <id property="id" column="ID" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  3. <result property="loginName" column="LOGIN_NAME" jdbcType="VARCHAR" javaType="java.lang.String"/>
  4. <result property="password" column="password" jdbcType="VARCHAR" javaType="java.lang.String"/>
  5. <result property="roleId" column="role_id" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  6. <association property="role" column="{id=role_id,name=role_name}" javaType="Role" select="selectRole"/>
  7. </resultMap>
  8. <select id="selectRole" parameterType="HashMap"  resultType="Role" >
  9. select * from Role where id =#{id} and name= #{name}
  10. </select>

这种方式很简单,但是对于大型数据集合和列表将不会表现很好。问题就是我们熟知的“N+1查询问题”。概括地讲,N+1查询问题可以是这样引起的:

你执行了一个单独的SQL语句来获取结果列表(就是“+1”)。
   对返回的每条记录,你执行了一个查询语句来为每个加载细节(就是“N”)。

这个问题会导致成百上千的SQL语句被执行。这通常不是期望的。

比如一个查询用户列表的SQL,假如有2000个用户,那么就是一个查询用户的SQL和2000个查询角色的SQL,一共有2001个SQL被运行。

MyBatis能延迟加载这样的查询就是一个好处,因此你可以分散这些语句同时运行的消耗。然而,如果你加载一个列表,之后迅速迭代来访问嵌套的数据,你会调用所有的延迟加载,这样的行为可能是很糟糕的。

所以还有另外一种方法。

关联的嵌套结果

嵌套结果

Xml代码  
  1. <resultMap  id="userResultMap" type="User">
  2. <id property="id" column="ID" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  3. <result property="loginName" column="LOGIN_NAME" jdbcType="VARCHAR" javaType="java.lang.String"/>
  4. <result property="password" column="password" jdbcType="VARCHAR" javaType="java.lang.String"/>
  5. <result property="roleId" column="role_id" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  6. <association property="role" column="role_id" javaType="Role" resultMap="roleResultMap"/>
  7. <id property="id" column="role_id"/>
  8. <result property="name" column="role_name"/>
  9. </association>
  10. </resultMap>
  11. <resultMap id="roleResultMap" type="Role">
  12. <id property="id" column="role_id"/>
  13. <result property="name" column="role_name"/>
  14. </resultMap>

也可以这样配置

Xml代码  
  1. <resultMap  id="userResultMap" type="User">
  2. <id property="id" column="ID" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  3. <result property="loginName" column="LOGIN_NAME" jdbcType="VARCHAR" javaType="java.lang.String"/>
  4. <result property="password" column="password" jdbcType="VARCHAR" javaType="java.lang.String"/>
  5. <result property="roleId" column="role_id" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  6. <association property="role" column="role_id" javaType="Role" resultMap="roleResultMap"/>
  7. </resultMap>
  8. <resultMap id="roleResultMap" type="Role">
  9. <id property="id" column="role_id"/>
  10. <result property="name" column="role_name"/>
  11. </resultMap>

resultMap这是结果映射的ID,可以映射关联的嵌套结果到一个合适的对象图中。这是一种替代方法来调用另外一个查询语句。这允许你联合多个表来合成到一个单独的结果集。这样的结果集可能包含重复,数据的重复组需要被分解,合理映射到一个嵌套的对象图。为了使它变得容易,MyBatis让你“链接”结果映射,来处理嵌套结果。一个例子会很容易来仿照,这个表格后面也有一个示例。

注意这个联合查询,以及采取保护来确保所有结果被唯一而且清晰的名字来重命名。

columnPrefix 属性

Xml代码  
  1. <association property="role" column="role_id" javaType="Role" resultMap="roleResultMap" columnPrefix="role_"/>
  2. <id property="id" column="id"/>
  3. <result property="name" column="name"/>
  4. </association>

非常重要:在嵌套据诶过映射中id元素扮演了非常重要的角色。应应该通常指定一个或多个属性,它们可以用来唯一标识结果。实际上就是如果你离开她了,但是有一个严重的性能问题时MyBatis仍然可以工作。选择的属性越少越好,它们可以唯一地标识结果。主键就是一个显而易见的选择(尽管是联合主键)。

上面你已经看到了如何处理“有一个”类型关联。但是“有很多个”是怎样的?下面这个部分就是来讨论这个主题的。

collection

collection关联元素处理一对多关联。

Xml代码  
  1. <resultMap  id="roleResultMap" type="Role">
  2. <id property="id" column="ID" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  3. <result property="name" column="NAME" jdbcType="VARCHAR" javaType="java.lang.String"/>
  4. <result property="userId" column="user_id" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  5. <collection property="user" column="user_id" javaType="ArrayList" ofType="Post" select="selectUser"/>
  6. </resultMap>
  7. <select id="selectUser" parameterType="java.lang.Long"   resultType="User" >
  8. select * from uer where id =#{id}
  9. </select>

同样,可以这样配置

Xml代码  
  1. <resultMap  id="roleResultMap" type="Role">
  2. <id property="id" column="ID" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  3. <result property="name" column="NAME" jdbcType="VARCHAR" javaType="java.lang.String"/>
  4. <result property="userId" column="user_id" jdbcType="NUMERIC" javaType="java.lang.Long"/>
  5. <collection property="user" column="user_id" javaType="ArrayList" ofType="Post">
  6. <id property="id" column="user_id"/>
  7. <result property="name" column="user_name"/>
  8. </collection>
  9. </resultMap>
  10. <resultMap id="userResultMap" type="User">
  11. <id property="id" column="user_id"/>
  12. <result property="name" column="user_name"/>
  13. </resultMap>

Mybatis中resultMap相关推荐

  1. MyBatis中resultMap详解

    MyBatis 中 resultMap 详解 resultMap 是 Mybatis 最强大的元素之一,它可以将查询到的复杂数据(比如查询到几个表中数据)映射到一个结果集当中.如在实际应用中,有一个表 ...

  2. 在mybatis中resultMap与resultType的区别

    MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap resultType是直接表示返回类型的,而resultMap则是对外部ResultM ...

  3. Mybatis中resultMap和resultType

    MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接 表示返回类型的,而resultMap则是对外部Result ...

  4. mybatis中resultMap和resultType的详细用法

    MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接 表示返回类型的,而resultMap则是对外部Result ...

  5. 后端技术:mybatis中resultMap用法示例笔记

    1.概念 resultMap属于mybatis返回操作结果的一个标签,可以用来映射select查询出来结果的集合,主要作用是将实体类中的字段与数据库表中的字段进行关联映射.并且支持复杂的返回结果类型. ...

  6. Mybatis中resultMap和resultType的区别

    MyBatis的每一个查询映射的返回类型都是ResultMap,只是当我们提供的返回类型属性是resultType的时候,MyBatis对自动的给我们把对应的值赋给resultType所指定对象的属性 ...

  7. mybatis中resultMap返回类型

    前面写了一篇关于resultType的文章,有兴趣的可以看看 这次写一篇resultMap的.就像官网上面说的"结果集的映射是 MyBatis 最强大的特性,对其有一个很好的理解的话,许多复 ...

  8. mybatis中resultMap和resultType区别,三分钟读懂

    先说结论: resultmap与resulttype的区别为:对象不同.描述不同.类型适用不同. 说人话就是,resultmap和resulttype功能差不多,但是resultmap功能更强大 re ...

  9. mybatis中resultMap标签中的extends属性有什么用?

    继承父类的resultMap,然后父类有的那一部分属性标签(id.result标签)就不用自己写了,例如: 子类: public class PromotionProduct extends PmsP ...

最新文章

  1. 我用Python爬取英雄联盟的皮肤,隔壁家的小弟弟都馋哭了
  2. python按日期排序_python按修改时间顺序排列文件的实例代码
  3. 多线程-单生产单消费模型
  4. 我们应学的11项技术[转载]
  5. python成绩转换_Python格式化输出%与format能不能互相转换?
  6. hadoop-KMS密钥管理服务配置使用
  7. 以太坊执行miner.start返回null终极解决方案
  8. Xshell和Xftp免费版下载安装
  9. Silverlight 4 全屏
  10. Raid5数据恢复算法原理- raid5数据恢复案例
  11. python音译爬虫_Python爬虫入门案例:获取百词斩已学单词列表
  12. Dev,SIT,UAT, Staging, Prod,DR环境分别是意思?
  13. 改进YOLOv5系列:首发结合 RepLKNet 构建 最新 RepLKDeXt 结构|CVPR2022 超大卷积核, 越大越暴力,大到31x31, 涨点高效
  14. Plotly 和 Dash 构建 Python 交互式仪表板类 App
  15. 职业能力倾向测试下什么软件,职业能力倾向测验
  16. 到底什么才是边缘计算?
  17. javascript常用知识点集
  18. echarts图表无数据无时,在页面显示暂无数据
  19. Fiddler+Proxifier进行PC端微信小程序抓包
  20. RationalDMIS 7.1读取点自动测量圆 2020

热门文章

  1. 什么叫大数据人物画像_大数据时代,如何构建精准用户画像,直击精细化运营...
  2. C语言(CED)输入一个任意长度的正整数,将该数逆序输出。
  3. Kettle之数据抽取、转换、装载
  4. 如何查询linux服务器的网卡,Linux服务器如何查看有没有无线网卡
  5. linux中权限765啥意思,Linux中的文件权限
  6. win7安装硬盘后无法启动计算机,硬盘装Win7系统电脑后开机提示DISK BOOT FAILURE怎么办【图文】...
  7. restful风格_什么是RESTful风格的API设计?
  8. centos7php自启动,centos7系统下nginx安装并配置开机自启动操作
  9. pos共识机制_OK区块链60讲 | 第17集:什么是PoS共识机制
  10. 【SpringBoot 2】(二)快速入门案例HelloWorld