一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
前言
在上文:Mybatis 入门篇(含实战)中,我们入门了 Mybatis,并且用 Spring 项目实现了一个接口到 MySQL 的增删查改,今天我们来聊聊 Mybatis 的 XML 映射器
XML 映射器是啥
以下片段截自官网
MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。
对于 Mybatis 来说,所有定制的 SQL 都维护在 XML 映射文件当中(也可以在 Mapper 层使用注解,但是功能性没有映射文件强),包括动态语句也是基于各种标签来灵活构建。
Dao/Mapper 接口与 XML 文件的关系
在最佳实践中,通常一个 XML 映射文件都会有一个 Dao/Mapper 与之相对应
学习 XML 映射文件,首先要明确几个概念
-
Dao 接口,也有人称为 Mapper 接口,接口的全限定名,就是 XML 文件中
namespace的值 -
每一个
<select>、<insert>、<update>、<delete>标签,都会被解析为一个MappedStatement对象 -
接口的方法名,就是映射文件中
MappedStatement的 Id 值 -
Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为 key 值,可唯一定位一个MappedStatement -
拿 5.3 的例子说,
cn.wzed.mybatisdemo.dao.StudentDao类下面的方法queryById,对应了StudentDao.xml文件中id = queryById的MappedStatement
一级标签
官方详细文档: mybatis – MyBatis 3 | XML 映射器
Mybatis 的一级标签并不多,掌握常用的几个即可
insert– 映射插入语句update– 映射更新语句delete– 映射删除语句select– 映射查询语句resultMap- 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素sql- 可被其它语句引用的可重用语句块
增删查改标签就不详细描述了,这里主要讲一下 resultMap 和 sql 标签
依旧拿 5.3 来举例
<resultMap type="cn.wzed.mybatisdemo.entity.Student" id="StudentMap">
<result property="id" column="id" jdbcType="INTEGER"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="age" column="age" jdbcType="INTEGER"/>
</resultMap>
动态 SQL
动态 SQL 是 MyBatis 的强大特性之一,如果你使用过 JPA 来自定义动态语句,你就会发现是有多么的痛苦,特别是写完后字符串拼接处忘记加空格
Mybatis 借助标签实现了动态语句,下面介绍一下用来构建动态语句的常用标签
if where
if经常与where搭配来构建简单的动态查询语句
还是以查询学生表为例,这是一个物理分页加使用条件动态查询的例子
<!--动态分页查询-->
<select id="queryAll" resultMap="StudentMap">
select
id, name, age
from student
<where>
<if test="student.id != null">
and id = #{student.id}
</if>
<if test="student.name != null and student.name != ''">
and name = #{student.name}
</if>
<if test="student.age != null">
and age = #{student.age}
</if>
</where>
limit #{pageNo}, #{pageSize}
</select>
在这个例子中,什么条件都不传会生成以下语句
select
id, name, age
from student
limit #{pageNo}, #{pageSize}
而当传入的 Student 对象中任意字段不为空时,会通过 if 标签的判断,从而加上 where 条件;假设传入的 id 不为空,会生成如下语句
select
id, name, age
from student
where id = #{student.id}
这里需要注意的是,Mybatis 会自动帮你祛除 where 后面的无用 and,用过 JPA 写自定义动态语句的人都表示泪目了!
choose、when、otherwise
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句
比如在 6.3.1 的例子中,我们想实现这样的效果:传入了 id,就根据 id 去查找,传入了 name 就根据 name 去查找,如果都不传,就默认查找年龄等于 18 的学生
<select id="queryByChooseTag" resultMap="StudentMap">
select
id, name, age
from student
<where>
<choose>
<when test="student.id != null">
and id = #{student.id}
</when>
<when test="student.name != null and student.name != ''">
and name = #{student.name}
</when>
<otherwise>
and age = 18
</otherwise>
</choose>
</where>
limit #{pageNo}, #{pageSize}
</select>
在这个例子中,假设传入了 id,会加上 where id = #{student.id} 条件,根据优先级,加上其他条件也是没用的;而当 id 为空,name 不为空时,会加上条件 where name = #{student.name};当两个字段都为空时,查询语句的条件是 where age = 18
其他标签……
set- 可以用于动态包含需要更新的列,忽略其它不更新的列foreach- 传入一个集合,通过foreach 可以构建 in 条件的语句- ……
鉴于常用的标签不多,用法也是类似的,在这里就不介绍这么多啦,上手就完事了