第6章 动态SQL
如果使用JDBC
或者类似于Hibernate
的其他框架,很多时候要根据需要去拼装SQL
,这是一个麻烦的事情。因为某些查询需要许多条件,比如查询角色,可以根据角色名称或者备注等信息查询,当不输入名称时使用名称作条件就不合适了。
通常使用其他框架需要大量的Java
代码进行判断,可读性比较差,而MyBatis
提供对SQL
语句动态的组装能力,使用XML
的几个简单的元素,便能完成动态SQL
的功能。大量的判断都可以在MyBatis
的映射XML
里面配置,以达到许多需要大量代码才能实现的功能,大大减少了代码量,这体现了MyBatis
的灵活、高度可配置性和可维护性。
6.1 概述
MyBatis的动态SQL包括以下一个元素
元素 | 作用 | 备注 |
---|---|---|
if | 判断语句 | 单条件分支判断 |
choose(when, otherwise) | 相当于JAVA中的switch和case语句 | 多条件分支判断 |
trim(where, set) | 辅助元素,用于处理特定的SQL组装问题,比如去掉多余的and、or等 | 用于处理SQL拼装的问题 |
foreach | 循环语句 | 在in语句等列举条件常用 |
6.2 if元素
if
元素相当于Java
中的if
语句,它常与test
属性联合使用
下面用一个场景来说明,根据角色名称(roleName
)来查找角色,如果roleName
不为空,则采取构造对roleName
的模糊查询,否则不要去构造这个条件
1 | <select id="findRoles" parameterType="string" resultMap="roleResultMap"> |
6.3 choose、when、otherwise元素
choose、when、otherwise
元素相当于java
中的switch...case...default..
下面用一个场景来说明
- 如果角色编号(
roleNo
)不为空,则只用角色编号作为条件查询。 - 当角色编号为空,而角色名称不为空,则用角色名称作为条件进行模糊查询。
- 当角色编号和角色名称都为空,则要求角色备注不为空。
1 | <select id="findRoles" parameterType="role" resultMap="roleResultMap"> |
6.4 trim、where、set元素
6.4.1 where元素
在6.3节的SQL
语句上的动态元素的SQL
中都加入了一个条件1=1
,如果没有加入这个条件,那么可能就变为了这样一条错误的语句:
1 | select role_no, role_name, note from t_role where and role_name like concat('%', #{roleName}, '%') |
我们可以使用where
元素来避免加入1=1
这个条件
1 | <select id="findRoles" parameterType="role" resultMap="roleResultMap"> |
当where
元素里面的条件成立时,才会加入where
这个SQL
关键字到组装的SQL
里面,否则就不加入
6.4.2 trim元素
有时候要去掉的是一些特殊的SQL
语法,比如常见的and
、or
。而使用trim
元素也可以达到预期效果
1 | <select id="findRoles" parameterType="string" resultMap="roleResultMap"> |
trim
代表要去掉一些特殊的字符串prefix
代表的是语句的前缀,而prefixOverrides
代表的是要去掉哪种字符串
6.4.3 set元素
在Hibernate
中常常因为要更新某一对象,而发送所有的字段给持久对象,而现实中的场景是,只想更新某一个字段。在MyBatis
中, 常常可以使用set
元素来避免这样的问题,比如要更新一个角色的数据
1 | <update id="updateRole" parameterType="role"> |
6.5 foreach元素
foreach
元素是一个循环语旬,它的作用是遍历集合,它能够很好地支持数组和List
、Set
接口的集合,对此提供遍历功能。它往往用于SQL
中的in
关键字。
1 | <select id="findUserBySex" resultType="user"> |
collection
配置的roleNoList
是传递进来的参数名称,它可以是一个数组、List
、Set
等集合index
配置的是循环中当前的元素index
配置的是当前元素在集合的位置下标open
和close
配置的是以什么符号将这些集合元素包装起来separator
是各个元素的间隔符
在SQL
中常常用到in
语句,但是对于大量数据的in
语句要特别注意,因为它会消耗大量的性能
6.6 用test的属性判断字符串
test
用于条件判断语句,作用相当于判断真假
6.7 bind元素
在进行模糊查询时,如果是MySQL
数据库,常常用到的是一个concat
,它用%
和参数相连。然而在Oracle
数据库则没有,Oracle
数据库用连接符号||
,这样SQL
就需要提供两种形式去实现。但是有了bind
元素,就不必使用数据库的语言,而是使用MyBatis
的动态SQL
即可完成。
1 | <select id="findRole" parameterType="string" resultType="com.bean.RoleBean"> |
这里的_parameter
代表的是传递进来的参数,它和通配符(%
)连接后赋给了pattern
,然后就可以在select
语句中使用这个变量进行模糊查询了。无论是MySQL
还是Oracle
都可以使用这样的语旬,提高了代码的可移植性。