1.为什么要进行resultType或resultMap注解配置

当需要实现的数据访问是查询类型的,在<select>节点中必须配置resultTyperesultMap中的某1个属性(二选一),如果都没有指定,则会出现如下错误:

Caused by: org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement 'cn.tedu.mybatis.UserMapper.count'.  It's likely that neither a Result Type nor a Result Map was specified.

解决因为名称不一致导致MyBatis无法自动封装查询结果的问题

  • 当自定义字段列表时,自定义别名,使得名称保持一致,并且,在<select>节点中使用resultType即可;
  • 当使用星号表示字段列表时,配置<resultMap>以指导MyBatis封装,并且,在<select>节点中使用resultMap应用配置的<resultMap>

2.resultType

其中,resultType指的就是“封装查询结果的数据的类型”,也可以理解为“抽象方法的返回值的类型”,例如可以配置为:

<select id="count" resultType="java.lang.Integer">SELECT COUNT(*) FROM t_user
</select>

如果某个查询的抽象方法的返回值是List集合类型的,例如:

List<User> findAll();

在配置<select>resultType属性时,该属性值必须是集合中的元素的类型,例如:

<select id="findAll" resultType="cn.tedu.mybatis.User">SELECT * FROM t_user ORDER BY id
</select>

注意:使用了这种做法后,就需要对抽象方法名称的定义增加一个要求“不允许重载”!

3.resultMap

3.1 一对一查询中的resultMap的使用

在没有自定义别名的情况下,如果查询结果的列名与类的属性名不一致,还可以自定义<resultMap>节点进行配置,该节点的作用就是指导MyBatis封装查询到的数据!

<!-- id:自定义的名称,将应用于select节点的resultMap属性 -->
<!-- type:封装查询结果的数据类型 -->
<resultMap id="UserMap" type="cn.tedu.mybatis.User"><!-- result节点:将查询结果中column列对应的值封装到类的property属性中去 --><result column="id" property="id"/><result column="username" property="username"/><result column="password" property="password"/><result column="age" property="age"/><result column="phone" property="phone"/><result column="email" property="email"/><result column="group_id" property="groupId"/>
</resultMap><select id="findById" resultMap="UserMap">SELECT*FROM t_user WHERE id=#{id}
</select>

在以上配置中,需要注意:<resultMap>节点中的id属性值就是<select>节点的resultMap属性值!

如果需要执行的查询操作是单表数据查询,在配置<resultMap>时,对于那些列名与属性名一致的,可以不作配置!

在配置<resultMap>时,推荐在子级使用<id>节点配置主键,然后使用<result>节点配置其它的,便于实现缓存!MyBatis有2级缓存,其中,MyBatis的1级缓存是SqlSession缓存,开发人员无法干预,2级缓存是namespace缓存,一旦开启,默认情况下,将作用于整个XML文件,需要事先在当前XML文件中添加<cache></cache>节点,表示“启用缓存”,理启用缓存,需要封装查询结果的数据类型是实现了Serializable接口的,如果某个查询不需要使用缓存,还可以在<select>节点中配置useCache="false",然后,就不需要开发人员进行其它配置了,MyBatis会自动处理缓存的数据,并且,一旦当前namespace执行了增删改类型的操作,就会重建缓存!

小结:在SQL中使用自定义别名,并在<select>中使用resultType指定封装结果的数据类型,或在SQL中使用星号表示字段列表,并配置<resultMap>节点后在<select>中使用resultMap,均可解决由于名称不一致导致无法封装查询结果的问题。

3.2 一对多查询中的resultMap的使用

在一对多的查询中,MyBatis根本就不知道怎么封装查询结果中的数据!当没有匹配的查询结果,或只有1条查询结果时,并不会报错,只是查询结果的数据不正确而已,如果查询结果有多条,则会出现如下错误信息:

Caused by: org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2

为了保障能够正确的封装查询结果,必须使用<resultMap>来指导MyBatis封装!并且,在SQL语句中,还需要为某个id定义别名,以保证查询结果每一列的名称都不同,否则,MyBatis只会从相同的列名中排列靠前的那一列中取数据,甚至,如果在<resultMap>中使用<id>配置主键,当出现多条数据的最靠前的那一列id值相同时,重复id的数据将不会被封装!

具体配置如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="cn.tedu.mybatis.GroupMapper"><resultMap id="GroupVOMap" type="cn.tedu.mybatis.GroupVO"><id column="gid" property="id" /><result column="name" property="name"/><!-- collection节点:用于配置1对多的属性 --><!-- ofType属性:集合元素类型 --><collection property="users"ofType="cn.tedu.mybatis.User"><id column="id" property="id"/><result column="username" property="username"/><result column="password" property="password"/><result column="age" property="age"/><result column="phone" property="phone"/><result column="email" property="email"/><result column="group_id" property="groupId"/></collection></resultMap><select id="findVOById" resultMap="GroupVOMap">SELECTt_group.id AS gid, name,t_user.*FROM t_groupLEFT JOINt_userONt_group.id=t_user.group_idWHEREt_group.id=#{id}</select></mapper>

注意:在配置一对多的查询时,在<resultMap>中,即使存在列名与属性名完全相同的数据,也必须通过<id><result>节点进行配置!

MyBatis框架学习:<select>节点中的resultType和resultMap属性相关推荐

  1. MyBatis框架学习 DAY_03:如何解决无法封装问题 / 一对一关联查询 / 一对多关联查询

    1. 通过查询时自定义别名的方式解决名称不一致而导致的无法封装数据的问题 假设,向用户组数据表(t_group)表中插入一些测试数据: INSERT INTO t_group (name) VALUE ...

  2. MyBatis中关于resultType和resultMap的区别

    使用resultType做自动映射时,要注意字段名和POJO的属性名必须一致. 使用resultType做自动映射时,可以不一致.但是你要想不一致.那么就必须在<mapper>标签下,添加 ...

  3. MyBatis框架学习 DAY_02:使用XML配置文件/多参数问题 / FOREACH /IF / #{}和${} / 创建SSM框架流程

    XML文件配置SQL 1. 使用XML文件配置SQL语句 2. 关于多参数的问题 2. 练习 3. 动态SQL -- foreach 4. 动态SQL -- if 5. 关于#{}和${}格式的占位符 ...

  4. mybatis框架--学习笔记(下)

    上篇:mybatis框架--学习笔记(上):https://blog.csdn.net/a745233700/article/details/81034021 8.高级映射: (1)一对一查询: ①使 ...

  5. mybatis框架--学习笔记(上)

    使用JDBC操作数据库的问题总结: (1)数据库连接,使用时创建,不使用时立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能. 设想:使用数据库连接池管理数据库连接. (2) ...

  6. 2021年3月8日:MyBatis框架学习笔记02:利用MyBatis实现CRUD操作

    MyBatis框架学习笔记02:利用MyBatis实现CRUD操作 在第一节课中我们在UserMapper.xml里定义了两个查询语句:findById和findAll,对应的在UserMapper接 ...

  7. spring struts2 mybatis框架学习总结(mvc三层架构)

    spring struts2 mybatis框架学习总结(mvc三层架构) ssi的框架主要是由struts2,spring以及ibatis组成,他们负责各层之间的交互与协作,从而实现整个web端的功 ...

  8. java中resulttype,深入理解Mybatis中的resultType和resultMap

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

  9. [Spring+SpringMVC+Mybatis]框架学习笔记(四):Spring实现AOP

    上一章:[Spring+SpringMVC+Mybatis]框架学习笔记(三):Spring实现JDBC 下一章:[Spring+SpringMVC+Mybatis]框架学习笔记(五):SpringA ...

最新文章

  1. 计算特征数据matlab代码,科学网—MATLAB特征提取代码 - 蒋样明的博文
  2. UVAlive 7041 The Problem to Slow Down You(回文树)
  3. 网上看的几点人生建议
  4. 安卓开发 新浪微博share接口实现发带本地图片的微博
  5. win7禁用Adnimistrator账号登录
  6. Data URL和图片,及Data URI的利弊
  7. python两个等号和一个等号_Python-一个变量等于另一个变量
  8. 面试准备每日五题:C++(八)——重写重载隐藏、vector相关
  9. JavaBean用JSP调用和使用JSP动作标签的区别
  10. 公寓式楼房宜南北走向
  11. [AHK]按住左键可以移动鼠标下的窗口
  12. 【源码】王者装逼工具/提升几倍的等级战力
  13. 预测身高c需语言,预测身高问题。不知哪出问题了,算出乱码。求解!
  14. 数据分析项目实战项目二:入驻商用户画像体系
  15. iOS 使用oc 版本的Lottie 库
  16. Pinyin4j 详解及使用
  17. swagger2 description is deprecated
  18. java web项目VO,dao,pojo,dto,bo,
  19. c语言做出的atm机怎样运行,c语言模拟ATM机界面
  20. 关于一行代码没写完换行\符号的注意

热门文章

  1. Linux内核中网络数据包的接收-第一部分 概念和框架
  2. java语法基础(总结)
  3. 填个小坑,Vue不支持IE8及以下,跨域ajax不支持IE9
  4. 配置Java网络应用程序的开发框架
  5. 【ZK-curator使用异常】KeeperErrorCode = Unimplemented for /***
  6. C#画图解决闪烁问题
  7. Js中最常见的异常捕捉 TryCatch
  8. 数据库连接池连接异常com.alibaba.druid.pool.GetConnectionTimeoutException
  9. NullPointerException异常的原因及java异常??
  10. 使用await / async时,HttpClient.GetAsync(...)永远不会返回