基于XML的Mapper配置 —— resultType 和 resultMap

我们之前已经介绍 MyBatis配置 ,这次就来看一看我们的映射文件,我们MyBatis是一个半自动的ORM框架,我们需要写一些的SQL语句,SQL语句主要写在我们的Mapper文件之间,这里可以把我们数据库中一行行的数据转换成我们的JavaBean对象。


我们先看看我们之前在 初识MyBatis 中是如何使用的
基于XML的Mapper配置 —— resultType 和 resultMap_第1张图片

在我们的Mapper文件中,第一个主要就是书写 Sql 语句,第二个就是我们数据库信息和我们的 POJO 类的映射。
我们这里就来 select 为例来查看一下其中可以设置哪些参数:

元素 说明 备注
id 它和Mapper的命名空间组合起来是唯一的,提供给MyBatis调用 如果命名空间和id组合起来不唯一,会抛出异常
parameterType 传入参数的类型;可以给出类全名,也可以给出类别名,使用别名必须是MyBatis内部定义或自定义的;
基本数据类型: int , String , long , date(不只是sql.date 还是 util.date)
复杂数据类型:类 和 Map
可以选择JavaBean, Map等复杂的参数类型传递给SQL
resultType 从这条语句中返回的期望类型的类的完全限定名或别名。
注意如果是集合情形,那应该是集合可以包含的类型,而不能是集合本身。
使用 resultType 或 resultMap,但不能同时使用
定义类的全路径,在允许自动匹配的情况下,结果集将通过JavaBean的规范映射;
或者定义为int,double,float等参数…
也可以使用别名,但是要符合别名规范,不能和resultMap同时使用。
它是我们常用的参数之一,比如我们总计总条数就可以把它的值设为int
resultMap 外部 resultMap 的命名引用。使用 resultMap 或 resultType, 但不能同时使用;它是映射集的引用,将执行强大的映射功能,我们可以使用resultType或者resultMap其中的一个, resultMap可以给予我们自定义映射规则的机会 它是MyBatis最复杂的元素,可以配置映射规则,级联, typeHandler等
flushCache 它的作用是在调用SQL后,是否要求MyBatis清空之前查询的本地缓存和二级缓存 true/false,默认为false
useCache 启动二级缓存开关,是否要求MyBatis将此次结果缓存 true/false,默认为true
timeout 设置超时时间,超时之后抛出异常,秒 默认值为数据库厂商提供的JDBC驱动所设置的秒数
fetchSize 获取记录的总条数设定 默认值是数据库厂商提供的JDBC驱动所设的条数

其中 id 就是和我们的Mapper接口一一对应的,parameterType 就是我们传入参数的Java类型,至于我们的 resultType 和 resultMap 我们不能同时使用,那么它们之间有什么区别呢?


resultType

我们先来看看 resultType ,resultType 是自动映射的,它引入的是我们类的全路径或者是类的别名(别名使用 typeAliases 进行设置。),它映射的规则就是数据库字段和我们的类字段同名,不同名则无法映射赋值,我们可以使用 as 给字段名起个别名。

另外如果数据库使用下划线,类使用驼峰,一种也是可以使用 as 别名,另外就是我们全局进行配置,就是 settings 下的 mapUnderscoreToCamelCase 设置为 true 即可。


但是在 MyBatis配置 中的 settings 配置中我们提到过我们是可以关闭我们的自动映射的,若我们将其设置为 NONE ,这样我们就无法自动映射了。
在这里插入图片描述


如下,我们还是使用之前博客说的例子,再不开启自动映射的情况下,我们的取出的结果为 null 。
基于XML的Mapper配置 —— resultType 和 resultMap_第2张图片


resultMap

那么当我们的自动映射关闭后,我们可以使用 resultMap 来解决,这里就需要我们手动的来一一设置数据库字段和POJO类字段的对应管理。
基于XML的Mapper配置 —— resultType 和 resultMap_第3张图片


上述我们谈到了 resultType 和 resultMap 的区别及用法,我们发现采用 resultType 自动映射是比较方便的,那么是不是我们就是比较推荐 resultType ?答案不是的,在阿里巴巴开发手册中,明确要求我们使用 resultMap 进行配置映射关系,以便以后若是我们的类字段发现了变化,或者数据库字段发现了变化,可以很好地维护。
在这里插入图片描述



既然阿里都推荐使用 resultMap 的话,那我们就来看一看我们 resultMap 的属性吧

属性 描述
id 当前命名空间中的一个唯一标识,用于标识一个result map
type 类的完全限定名, 或者一个类型别名
autoMapping 如果设置这个属性, MyBatis将会为这个 ResultMap 开启或者关闭自动映射。这个属性会覆盖全局的属性 autoMappingBehavior。默认值为: unset。

基于XML的Mapper配置 —— resultType 和 resultMap_第4张图片
至于 autoMapping 我们一般不进行配置,因为我们既然使用了 resultMap 就是准备手动的进行一一映射,我们为什么要在 resultMap 里面进行字段的自动映射呢,那还不如直接使用 resultType 方便。


我们看完 resultMap 元素后,我们再来看看其常用的子元素

属性 描述
constructor 用于在实例化类时,注入结果到构造方法中
constructor_idArg ID 参数;标记出作为 ID 的结果可以帮助提高整体性能
constructor_arg 将被注入到构造方法的一个普通结果
id 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能
result 注入到字段或 JavaBean 属性的普通结果
association 一个复杂类型的关联;许多结果将包装成这种类型
嵌套结果映射 – 关联可以指定为一个 resultMap 元素,或者引用一个
collection 一个复杂类型的集合
嵌套结果映射 – 集合可以指定为一个 resultMap 元素,或者引用一个
discriminator 使用结果值来决定使用哪个 resultMap
discriminator_case 基于某些值的结果映射
嵌套结果映射 – 一个 case 也是一个映射它本身的结果,因此可以包含很多相同的元素,或者它可以参照一个外部的 resultMap
属性 描述
property 映射到列结果的字段或属性。如果用来匹配的 JavaBeans 存在给定名字的属性,那么它将会被使用。否则 MyBatis将会寻找给定名称 property 的字段。 无论是哪一种情形,你都可以使用通常的点式分隔形式进行复杂属性导航。
column 数据库中的列名,或者是列的别名。一般情况下,这和 传递给 resultSet.getString(columnName) 方法的参数一样。
javaType 一个 Java 类的完全限定名,或一个类型别名(参考上面内建类型别名 的列表) 。如果你映射到一个 JavaBean,MyBatis通常可以断定类型。 然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证期望的行为。
jdbcType JDBC 类型,所支持的 JDBC 类型参见这个表格之后的“支持的 JDBC 类型”。 只需要在可能执行插入、更新和删除的允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。如果你直接面向 JDBC 编程,你需要对可能为 null 的值指定这个类型。
typeHandler 使用这个属性,你可以覆盖默 认的类型处理器。这个属性值是一个类型处理 器实现类的完全限定名,或者是类型别名。

在这里插入图片描述
(ps:column字段不是指定特定表中的指定,它可能指多个表,是针对 sql 语句而言的。)



上表中大部分我们都已经使用过了,这里我们在补充一个 constructor 的用法。
基于XML的Mapper配置 —— resultType 和 resultMap_第5张图片

这个是有什么用呢?就是为了解决我们需要映射的 POJO 没有对应的无参构造方法


我们都知道一个类要是没有任何构造方法,它默认会有一个无参的构造方法,但是我们如果设置了一个有参构造方法,那么它就不会默认为我们提供无参构造方法了,所以我们我们在代码规范中,一般要求添加了有参构造方法,就必须提供无参构造方法。


下面我们为我们 resultMap 映射的类只提供一个有参构造方法
基于XML的Mapper配置 —— resultType 和 resultMap_第6张图片

运行测试代码,程序就报错了,因为它默认会调用我们的无参构造方法,这里我的 User 类不存在无参构造方法
基于XML的Mapper配置 —— resultType 和 resultMap_第7张图片

既然不存在无参构造方法,那我们就来使用有参构造方法来试试
基于XML的Mapper配置 —— resultType 和 resultMap_第8张图片


这里我们需要多提一句,就是我们的 resultMap 映射时,不是必须要求 Setter 方法的,要是没有 Setter 方法能不能映射成功呢?

也是可以的,我们 MyBatis 在映射时,不是简单的利用我们的反射来完成的,它如果不存在 Setter 方法,那么我们在反射过程中会进行处理,生成了相应的Setter/Getter方法,最后来完成我们字段的映射过程。

你可能感兴趣的:(MyBatis)