题目
xml 映射文件中,除了常见的 select/insert/update/delete 标签之外,还有哪些标签
答案
@[toc]
---
## 一级标签
The Mapper XML files have only a few first class elements (一级标签):
- `cache` – Configuration of the cache for a given namespace. 给定命名空间的缓存配置
- `cache-ref` – Reference to a cache configuration from another namespace. 引用来自另一个命名空间的缓存配置
- `resultMap` – The most complicated and powerful element that describes how to load your objects from the database result sets(描述如何从数据库结果集中加载对象),详细可擦考这篇文章 [MyBatis中强大的resultMap](https://juejin.cn/post/6844903858477481992)
> 如果数据库中表的字段与 `User` 类的属性名称一致,我们就可以使用 `resultType` 来返回(注意这是 resultType!而不是 resultMap)。
>
> ```xml
> <select id="getUsers" resultType="User">
> SELECT
> u.id,
> u.username,
> u.password,
> u.address,
> u.email
> FROM
> USER u
> </select>
> ```
>
> 当然,**这是理想状态下,属性和字段名都完全一致的情况**。但事实上,不一致的情况是有的,这时候我们的`resultMap`就要登场了。
>
> 如果 `User` 类保持不变,但`SQL`语句发生了变化,将`id`改成了`uid`。
>
> ```xml
> <select id="getUsers" resultType="User">
> SELECT
> u.id as uid,
> u.username,
> u.password,
> u.address,
> u.email
> FROM
> USER u
> </select>
> ```
>
> 那么,在结果集中,我们将会丢失 `id` 数据。这时候我们就可以定义一个`resultMap`,来映射不一样的字段。
>
> ```xml
> <resultMap id="getUserByIdMap" type="User">
> <result property="id" column="uid"></result>
> </resultMap>
> ```
>
> 然后,我们把上面的 `select` 语句中的 `resultType` 修改为 `resultMap="getUserByIdMap"`。
>
> 这里面 `column` 对应的是数据库的列名或别名;`property` 对应的是结果集的字段或属性。
>
> 这就是 `resultMap` 最简单,也最基础的用法:字段映射。
- ~~`parameterMap`~~ – **Deprecated!** Old-school way to map parameters. Inline parameters are preferred and this element may be removed in the future. Not documented here.
- `SQL` – This element can be used to define a reusable fragment of SQL code that can be included in other statements. 可以被其他语句 included 的可重用的 SQL 块
> 举个例子:
>
> ```xml
> <SQL id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </SQL>
> ```
>
> The SQL fragment can then be included in another statement, for example:
>
> ```xml
> <select id="selectUsers" resultType="map">
> select
> <include refid="userColumns"><property name="alias" value="t1"/></include>,
> <include refid="userColumns"><property name="alias" value="t2"/></include>
> from some_table t1
> cross join some_table t2
> </select>
> ```
- `insert` – A mapped INSERT statement.
- `update` – A mapped UPDATE statement.
- `delete` – A mapped DELETE statement.
- `select` – A mapped SELECT statement.
## 动态标签
- `if`:有条件地包含 where 子句的一部分
> 举个例子:
>
> ```xml
> <select id="findActiveBlogWithTitleLike" resultType="Blog">
> SELECT * FROM BLOG
> WHERE state = ‘ACTIVE’
> <if test="title != null">
> AND title like #{title}
> </if>
> </select>
> ```
- `choose`,`when`,`otherwise`:有时我们不希望所有条件都适用,而是希望**在众多选项中仅选择一种情况**。与 Java 中的 switch 语句类似
> 举个例子:
>
> ```xml
> <select id="findActiveBlogLike"
> resultType="Blog">
> SELECT * FROM BLOG WHERE state = ‘ACTIVE’
> <choose>
> <when test="title != null">
> AND title like #{title}
> </when>
> <when test="author != null and author.name != null">
> AND author_name like #{author.name}
> </when>
> <otherwise>
> AND featured = 1
> </otherwise>
> </choose>
> </select>
> ```
- `trim`,`where`,`set`:用来截断在 if 语句中冗余的字段
> 举个例子:
>
> ```xml
> <select id="findActiveBlogLike"
> resultType="Blog">
> SELECT * FROM BLOG
> WHERE
> <if test="state != null">
> state = #{state}
> </if>
> <if test="title != null">
> AND title like #{title}
> </if>
> <if test="author != null and author.name != null">
> AND author_name like #{author.name}
> </if>
> </select>
> ```
>
> **What happens if none of the conditions are met?** You would end up with SQL that looked like this:
>
> ```xml
> SELECT * FROM BLOG
> WHERE
> ```
>
> This would fail.
>
> MyBatis 有一个简单的解决方案,把 where 改成 `<where>` 标签
>
> ```xml
> <select id="findActiveBlogLike"
> resultType="Blog">
> SELECT * FROM BLOG
> <where>
> <if test="state != null">
> state = #{state}
> </if>
> <if test="title != null">
> AND title like #{title}
> </if>
> <if test="author != null and author.name != null">
> AND author_name like #{author.name}
> </if>
> </where>
> </select>
> ```
>
> where 标签知道只有在返回内容时才插入 “WHERE”。此外,如果该内容以“AND”或“OR”开头,它知道将其删除。
>
> 与 `<where>` 标签类似的是还有 `<set>`
>
> 当然,如果这俩无法满足你的需求,可以采用 `trim`,比如:
>
> ```xml
> <trim prefix="WHERE" prefixOverrides="AND |OR ">
> ...
> </trim>
> ```
- `foreach`:iterate over a collection,在 SQL 中迭代一个集合
> 举个例子:
>
> ```xml
> <select id="selectPostIn" resultType="domain.blog.Post">
> SELECT *
> FROM POST P
> <where>
> <foreach item="item" index="index" collection="list"
> open="ID in (" separator="," close=")" nullable="true">
> #{item}
> </foreach>
> </where>
> </select>
> ```
