前言:
上一章学习了MyBatis的基础知识,搭建了MyBatis的开发环境,掌握了MyBatis的核心类和接口的作用域及其生命周期,并熟悉了核心配置文件的结构。
今天学习 MyBatis 基本要素中的 SQL 映射文件
并利用 SQL 映射文件进行 增、删、改、查操作。
单词:
ResultType 返回结果类型
ResultMap 返回结果映射
Association 一对一关联映射
Collection 一对多关联映射
Cache 缓存
ParameterType 参数类型
SQL映射文件
MyBatis 强大之处就在于SQL映射语句。
相对于它的强大功能,它的配置却非常简单。
MyBatis 专注于SQL,对于开发人员来说,也可极大限度地进行优化SQL,来保证性能。
MyBatis 的SQL映射文件中的Mapper元素的 namespace 属性有两个要求:
namespace的命名必须和DAO接口同名,同属于DAO层。
故代码结构上,映射文件与该DAO接口应放置在同一个 package 下。
并且都要以 xxx.mapper 命名。
在不同的 mapper文件中,子元素的 id 可以相同, MyBatis 通过 namespace 和子元素的id 联合区分。
接口中的方法与映射文件中 SQL 语句 id 应 一一对应。
使用 select 完成单个查询
与查询相对应的 select 元素是使用 MyBatis 最常见的元素。
这是一个 id 为 getUserListByUserName 的映射语句,对应的是接口中的
getUserListByUserName( String userName) 的方法。
参数类型为 String, 返回结果的类型是 User 对象类型
为了使数据库查询的结果和返回类型中的属性能够自动匹配以便开发,对于 MySQL数据库和 JavaBean都会采用 一套相同的命名规则,也就是 Java命名驼峰规则,这样的就不需要再做映射。
但是如果数据库表的字段名和属性名不一致的的话需要进行手动映射。
Id 属性:
命名空间的唯一的标识符,可以被用来引用这条语句。
ParameterType 属性:
表示查询语句传入参数的类型完全限定名或者别名
它支持基础数据类型和复杂数据类型。
“string” 是一个别名,代表 String 字符串数据类型
属于一个内建的类型别名,对应普通常见的 Java数据类型, 都是有内建别名的。
并且它们对于大小写并不敏感
除了内建的类型别名外,还可以为自定义的类设置别名
然后就可以在映射文件中直接使用别名,以减少配置文件的代码。
ResultType 属性:
查询语句返回结果类型的完全限定名或者别名
使用 select 完成多条件查询
(1)ParameterType 使用了复杂数据类型,把条件参数封装到 对象进行入参。
(2)复杂数据类型除了 Javabean 外,还可以使用 Map类型进行入参。
这种做法更加灵活,不管多少个参数,或什么样的数据类型,都可以把它封装成 Map数据结构进行入参,通过Map的 key 即可获取传入的值。
Mybatis 传入参数类型可以是 Java基本数据类型,但是只适用于一个参数的情况下
通过 #{参数名} 的方式即可获得传入的值。
若是多参数入参,则需要复杂数据类型来支持, 包括 Java实体类、Map、
通过 #{属性名} 或 #{Map 的 key} 来获取传入的值。
使用resultMap完成查询结果的展现
Mybatis 中使用 resultType 做自动结果映射,但是一定要注意的是
表中的字段名和 pojo 属性名必须要保持一致。
若不一致,则需要给字段名起别名,保证别名和属性名一致。
使用resultMap 可以手动做自定义结果映射,字段名可以不一致
并且还可以知道要显示的列,比较灵活。
ResultMap 元素的属性值和字节点:
id 属性:唯一标识,此 id 值用于 select元素 resultMap属性的引用。
Type 属性:表示了该 resultMap的映射结果类型。
Result 字节点:用于标识一些简单属性,其中 Column属性表示从数据库中查询的字段名,property 则表示查询出来的字段对象的值赋给实体对象中的那个属性。
resultType:
直接表示返回类型,包括基础数据类型和复杂数据类型
resultMap:
是对外部 resultMap 的引用,对应了外部 resultMap 的id,
表示把返回结果映射到哪一个resultMap上。
如果数据库字段信息和对象属性不一致或者需要做复杂的联合查询以便自由控制映射结果的时候经常使用 resultMap。
ResultType 和 resultMap的关联
在MyBatis进行查询映射的时候,其实查询出来的每个字段值都是放在一个对应的Map里面,其中键是字段名,值是对应的值。
Mybatis 的每个查询映射的返回类型都是 resultMap类型
我们提供的返回类型是resultType的时候,MyBatis会自动把对应的值赋值给 resultType所指定的对象的属性
因为Map不能很好地表示领域模型,我们就需要通过进一步的定义把它转化为对应的实体对象
在MyBatis的 select元素中,resultMap和resultType本质上是一样的,都是Map数据结构
但是这两个属性绝对不能同时存在,只能二者选一。
使用insert 完成增加操作
对于增删改这类数据库操作,需要注意两点:
- 该类型的操作本身默认返回SQL影响的行数,所有Dao层的接口方法的返回值返回值一般设置为 int 类型。
- Insert、update、delete元素中均没有 resultType属性,只有查询操作需要对返回结果进行相应的映射。
使用 update 完成修改操作
使用 @param 注解实现多参数入参
使用注解 @param 来传入多个参数,代码的可读性高,可以清晰地看出这个接口所需的参数是什么
在MyBatis中,超过四个参数以上的最好封装成对象进行入参。
对于参数固定的业务方法,最好使用多参数入参,这种方法比较灵活。
对于固定的接口方法,参数一般是固定的,所有可以直接使用多参数入参,无须封装对象。
需要注意,当参数为基础数据类型时,不管是多参数入参还是单参数入参,都需要 @param
注解来进行参数传递。
使用 delete 完成删除操作
使用 resultMap实现高级结果映射
Association
Association映射到 JavaBean的某个 “复杂类型”属性,比较一个 JavaBean类
也就是一个JavaBean 内部嵌套了一个复杂数据属性
不过Association只能处理一对一的关联关系。
JavaType : 完整Java类名或者别名
若映射到一个 JavaBean, 则MyBatis通常会自动检测到其类型。
若映射到一个HashMap,则应该明确指定 javaType, 来确保所需的行为。
在做映射结果的时候,需要确保所有的列名都是唯一且无歧义的。
Id 子元素在嵌套结果映射中有很重大的作用,应该指定一个或多个属性来唯一标识这个结果集
就算没有指定 子元素 id,MyBatis也能进行运行,但是会造成很严重的性能开销。
Collection
Collection 元素的作用和 association元素的作用差不多一样,它们很类似
也是映射 JavaBean的某个复杂属性上面。
只不过这个属性是一个集合列表。
OfType : 完整的类名或者别名,即集合类型所包含的类型。
resultMap 自动映射级别
MyBatis对于 resultMap有三个映射级别
NONE : 禁止自动匹配
PARTLAL : 默认属性,自动匹配所有的属性,有内部嵌套的除外。
FULL : 自动匹配所有
MyBatis缓存
和大多数的持久化框架一样,MyBatis提供了一级缓存和二级缓存的支持。
一级缓存是基于 perpetualCache 的HashMap本地缓存,作用域范围是 session 域内,
当 session flush 或者 close 后,该session中所有的 Cache就会被清空。
这是 MyBatis 自带的缓存机制。
二级缓存就是 global caching,它超出了 session的范围之外,可以被所有的 Sqlsession共享,开启它需要在 MyBatis的核心配置文件中 settings 中进行设置。
在mapper文件中设置缓存,默认情况下是没有开启缓存的。
在mapper文件配置支持 cache后,还可以对个别查询单独设置 cache.
对于MyBatis的缓存只需要知道即可,因为面对一定规模数据量的时候,内置的Cache方式就不用到了,
并且对查询结果集做缓存并不是 MyBatis框架所擅长的
它专心做的是SQL映射。
总结:
MyBatis 的SQL 映射文件提供了 select、insert、update、delete等元素来实现SQL语句的映射
SQL映射文件的根节点是 mapper 元素,需要制定 namespace 来区别于其他的 mapper
保证全局唯一性,并且其名称必须和接口同名,作用是和Dao接口进行绑定,也就是面向接口编程。
SQL映射文件的select的返回结果类型的映射可以使用resultMap和resultType,但是不能同时存在
对于基本数据类型的参数数据,使用 @param注解进行入参,繁杂数据类型的参数直接入参即可。
ResultMap的 association 和 collection 可以实现高级结果映射。