MyBatis 动态 SQL
如果使用JDBC或者类似于Hibernate的其他框架,很多时候要根据需要去拼装SQL,这是一个麻烦的事情。因为某些查询需要许多条件,比如查询角色,可以根据角色名称或者备注等信息查询,当不输入名称时使用名称作条件就不合适了。通常使用其他框架需要使用名称条件就不合适了。通常使用其他框架需要大量的Java代码进行判断,可读性比较差,而MyBatis提供对SQL语句动态的组装能力,使用XML的几个简单的元素,便能完成动态SQL的功能。大量的判断都可以在MyBatis的映射XML里面配置,以达到许多需要大量代码才能实现的功能,大大减少了代码量,这体现了MyBatis的灵活、高度可配置性和可维护性。
概述
MyBatis的动态SQL包括一下几种元素。
元素 | 作用 | 备注 |
---|---|---|
if | 判读语句 | 单条件分支判断 |
choose(when,otherwise) | 相当于java中的switch和case语句 | 多条件分支判断 |
trime(where,set) | 辅助元素,用于处理特定的SQL拼装问题,比如去掉多余的and、or等 | 用于处理SQL拼装成的问题 |
forearch | 循环语句 | 在in语句等列举条件常用 |
动态SQL实际使用的元素并不多,但是他们带来了灵活性,减少了许多工作量的同时,也在很大程度上提高了程序的可读性和可维护性。
if元素
if元素是最常用的判断语句,相当于Java中的if语句,他尝尝与test属性联合使用。
if元素十分简单,举例说明如何使用它。先进行简单的场景描述:根据角色名名称去查找角色,但是角色名称是一个选填条件,不填写时,就不要用做它作为条件查询。这是查询中最常见的场景之一。
<select id="findRoles" parameterType="string" resultMap="roleResultMap">
select * from t_role where 1=1
<if test="roleName != null and roleName !=''">
and role_name like concat('%',#{roleName}, '%')
</if>
</select>
choose when otherwise 元素
上边的代码中相当于 java 语言中的 if 语句,不是这个就是那个。有时候还需要第三种选择,甚至更多选择,也就是类似 switch-case-default 功能的语句。在映射器的动态语句中 choose、when、otherwise 这三个元素承担了这个功能。假设有这样一个场景:
- 如果角色编号不为空,则只用角色编号作为查询条件
- 当角色编号为空,而角色名称不为空,则用角色名称作为条件进行模糊查询。
- 当角色编号和角色名称都为空,则要求角色备注不为空。
这个场景可能有点不切实际,这里主要集中于如何使用动态元素来实现它。
<select id="findRoles" parameterType="role" resultMap="roleResultMap">
select role_no,role_name,note from t_role
where 1=1
<choose>
<when test="roleNo != null and roleNo !=''">
and role_no = #{roleNo}
</when>
<when test="roleName != null and roleNo !=''">
and role_name like concat('%',#{roleName}, '%')
</when>
<otherwise>
and note is not null
</otherwise>
</choose>
</select>
trim、 where、set 元素
细心的话,可以发现上边的SQL语句的动态元素SQL中都加入了一个条件 “1=1” 如果没有这个条件,那么可能就会变成了一条错误的语句。
MyBatis 有一个简单的处理,这在 90% 的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能达到目的:
<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 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。
更多动态SQL的特性可以到MyBatis官方文档查看。