前言
我们深入Sql映射文件,进行增删改查。这篇博客的重点是 查,其次添加删除修改。
MyBatis实现条件cha查询
Sql映射文件
MyBatis 真正的强大在于映射语句,专注于SQL,功能强大,SQL映射的配置却是相当简单,首先了解映射文件的几个顶级元素配置:
- mapper:映射文件的跟元素节点,只有一个属性namespace(命名空间 )作用:
(1)区分不同的mapper,全局唯一
(2)绑定DAO接口,及面向接口编程。当namespce绑定某一接口之后,可以不用写该接口的实现类,MyBatis会通过接口的完整限定名查找到对应的mapper配置来执行SQL语句,因此namespace的命名必须要跟接口同名。 - cache:给定命名空间的缓存
- cache-ref:从其它命名空间引用缓存配置。
- resultMap:用来描述数据库结果集和对象的对应关系。
- sql:可以重用的SQL块,可以被其他Sql语句引用
- insert – 映射插入语句
- update – 映射更新语句
- delete – 映射删除语句
- select – 映射注意查询语句
注意
(1)namespace命名必须跟某个DAO接口同名同属DAO层,所以代码结构上,映射文件与DAO接口放在同包下,并且XML习惯以mapper结尾。
(2)在不同的mapper文件中,子元素的id可以相同,MyBatis通过namespace和子元素的id联合区分,接口中的方法与映射文件中的SQL语句一 一对应。
select
select是MyBatis中最常用的元素之一,
select语句有很多属性可以详细配置每一条语句
-
id:命名空间中唯一的标识符,接口中的方法与映射文件中的SQL语句id一一对应
-
parameterType:传入SQL语句的参数类型
-
resultType 直接表示返回类型包括 基础数据类型 和 复杂数据类型。
-
SQL映射文件的select的返回结果类型的映射可以使用resultMap和resultType,但不能同时使用。
-
resultMap 则是对外部resultMap定义的引用,对外部resultMap的Id,表示返回结果映射到哪一个resultMap上。【它的应用场景一般是 数据库字段信息与对象属性不一致 或者需要做复杂的联合查询以便自由控制映射结果。】
MyBatis传参有几种方式?
- 对象入参
超过3个以上的参数最好封装成对象入参
- Map入参
这种方法很灵活,不管是什么参数类型,有多少个参数,都可以把他封装成Map进行入参,通过map的Key(键)来获取。
- @Param注解实现参数传入
参数固定的业务方法,最好使用多参数入参
使用resultMap完成查询
实际开发中,要查询的表肯定不止一个,大部分都是多表查询,问题来了,多张表的数据,和实体类是无法对应的,那怎么办,有以下几种方法。
- 修改实体类(pojo):可以修改sql语句和pojo,可以使用resultType做自动映射(需要注意的是:字段名和属性名是否一致,若不一致,那么需要给字段起别名,变成一致),对于列表要求显示指定字段(可以通过sql查询字段来控制)
- 通过resultMap来映射自定义结果
推荐第二中方法,resultmap做自定义映射结果,字段名可以不一致,并且还可以指定要显示的列,比较灵活,运用页比较广泛。
resultMap
resultMap元素用来描述如何将结果映射到Java对象,此处用resultMap对列表展示所需的字段,来进行自由映射。特别是当数据库名和POJO(实体类)中的属性名不一致的时候要做映射。
resultMap元素属性值和子节点:
- id属性:表示唯一,此id值用于select元素resultMap属性的引用。
- type属性:表示映射的结果类型
- result子节点:标识一些简单的属性,其中column属性表示数据库查询的字段名,property属性表示查询出来的值赋实体类对象的哪个属性。
resultType和resultMap的关联和区别?
-
resultType :直接表示返回类型
基本数据类型
复杂数据类型 -
resultMap :对外部resultMap的引用
应用场景:
(1)数据库字段信息与对象属性不一致
(2)复杂的联合查询,自由控制映射结果
(3)二者不能同时存在,本质上都是Map数据结构 -
resultType和resultMap关联
MyBatis查询的时候,其实查询出来的值都存放在 Map 中,其中 键 是字段名,值时对应的值。当 select 提供的返回类型属性为 resultType的时候,MyBatis会将Map里面的jianzhi键值取出赋 resultType 。 -
resultMap的自动映射级别
<settings>
<setting name="autoMappingBehavior" value="NONE"/>
</settings>
resultMap的自动映射级别-autoMappingBehavior
- PARTIAL(默认):自动匹配所有,内部嵌套除外(collection,association)。
- NONE:禁止匹配所有
- FULL:自动匹配所有。
MyBatis实现增删改
注意:insert、update、delete元素均没有resultType属性
- insert
(1)id属性:命名空间中唯一的标识,可以被用来引用这条语句
(2)parameterType属性:传入的参数类型
<insert id="add" parameterType="User" >
insert into smbms_user (userCode,userName,userPassword)
values ( #{userCode},#{userName},#{userPassword})
</insert>
- update
(1)id属性:命名空间中唯一的标识,可以被用来引用这条语句
(2)parameterType属性:传入的参数类型
<update id ="modify" parameterType="User">
update smbms_user set userCode = #{userCode},
userName = #{userName},
userPassword = #{userPassword} where id = #{id}
</update>
- delete
(1)id属性:命名空间中唯一的标识,可以被用来引用这条语句
(2)parameterType属性:传入的参数类型
<delete id ="deleteUserById" parameterType="int">
delete from smbms_user where id = #{id}
</delete>
- 使用@Param实现多参数入参
扩展:
在《练习:在超市订单系统中实现订单表的查询操作》中,提出使用多参数入参的方式进行订单表的查询操作。
若不使用@Param注解,则会报错,报错信息类似于Parameter ‘参数名’ not found。探究原因,需要深入MyBatis源码:
1) MyBatis的参数类型为Map,若使用@Param注解参数,那么就会记录指定的参数名为key;
2) 若参数钱没有加@Param,那么就会使用“param”+它的序号作为Map的key。
故在进行多参数入参时,若没有使用@Param指定参数,那么在映射的SQL语句中获取不到#{参数名},从而报错。
传入一个参数的时候可以不需要注解,但是多个参数的时候必须使用注解
public int updatePwd(@Param("id") Integer id, @Param("userPassword") String pwd);
使用注解@Param来传入多个参数,如@Param(“userPassword”) String pwd),相当于将该参数pwd重命名为userPassword。在映射的SQL中需要使用#{注解名称},如#{userPassword}。
使用resultMap实现高级映射结果
回顾一下resultMap的基本配置
属性:
- id:唯一标识
- type:表示resultMap映射的结果类型(通常Java实体类)
子节点:
- id:一般对应数据库中的主键id,设置此项可以提高MyBatis的性能
- result:映射到Javabean属性。
Association
Association:映射到某个"复杂类型"属性,比如JavaBean类,即JavaBean内部嵌套复杂数据类型(JavaBean)属性,这种情况就属于复杂类型的关联,需要注意Association是一对一关联关系。
分析Association的属性:
- javaType:完整的Java类名或者别名
- property:映射数据库列的实体对象的属性
- resultMap:引用外部resultMap
子元素
- id
- result
- property:映射数据库列的实体
- column:数据库列明或者别名
collection
collection:collection元素作用和Association元素差不多一样,也是映射到JavaBean的某个复杂数据类型属性,只不过这个属性是一个集合列表,即JavaBean内部嵌套一个复杂数据类型(集合)属性,和使用Association元素一样,我们使用嵌套查询,或者连接中嵌套结果集。collection是一对多特性。
属性:
- property:映射数据库列的实体对象的属性
- ofType:完整Java类名或者别名(集合所包括的类型)
- resultMap:引用外部resultMap
子元素
- id
- result
- property:映射数据库列的实体对象的属性
- column:数据库列名或者别名
MyBatis缓存
一级缓存:一级缓存时基于PerpetualCache(MyBatis自带)的HashMap本地缓存,作为范围为session域内,当session flush或者close之后,该session中所有cache就会清空。
二级缓存:二级缓存就是global caching,它超过session范围之外,可以被所有SqlSession共享,开启它只需要在MyBatis的核心配置文件(mybatis-config.xml)settings中设置即可。