动态SQL是MyBatis的一个强大特性。在编写sql语句时,尝尝需要根据不同条件拼接sql语句,动态sql帮助开发者非常轻松地实现各种条件下的sql拼接。
下面是MyBatis提供的基于OGNL的动态SQL表达式。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
if 语句
动态SQL中一个常见做法是有条件包含where子句。
示例:
<select id = "getByName" parameterType = "User" resultType = "User">
SELECT * FROM User
<if test = "name != null">
WHERE name LIKE #{name}
</if>
</select>
此语句查询用户列表,如果提供了用户名称,则根据用户名(like 匹配)查询用户。
可以包含多个if条件,如下所示:
<select id = "getByName" parameterType = "User" resultType = "User">
SELECT * FROM User
<if test = "name != null">
WHERE name LIKE #{name}
</if>
<if test = "id != null">
AND id = #{id}
</if>
</select>
choose, when, otherwise语句
MyBatis提供了一个<choose>
标签,类似Java的switch语句,可以在多个选项中只选择一个生效。
下面的示例,如果name不为空,根据name查询用户,如为空,接着判断下一个条件:如果id不为空,根据id查询用户,如果都不满足进入otherwise分支。
<select id = "getByNameOrId" parameterType = "User" resultType = "User">
SELECT * FROM User
<choose>
<when test = "name != null">
WHERE name LIKE #{name}
</when>
<when test = "id != null">
WHERE id = #{id}
</when>
<otherwise>
WHERE 1
</otherwise>
</choose>
</select>
where, set 语句
看前面的例子:
<select id = "getByName" parameterType = "User" resultType = "User">
SELECT * FROM User
<if test = "name != null">
WHERE name LIKE #{name}
</if>
<if test = "id != null">
AND id = #{id}
</if>
</select>
如果前一个条件不满足,后面条件满足,生成的sql语句是错的,如下所示:
SELECT * FROM User
AND id = xxx
mybatis的<where>
标签可解决此类问题:
<select id = "getByName" parameterType = "User" resultType = "User">
SELECT * FROM User
<where>
<if test = "name != null">
name LIKE #{name}
</if>
<if test = "id != null">
AND id = #{id}
</if>
</where>
</select>
<where>
标签只在标签内至少有一个条件成立时才插入where,另外,如果内容以AND或OR开头,mybatis会自动去掉AND与OR。
类似<where>
,动态更新时可以使用<set>
,<set>
标签可以用于动态包含需要更新的列。
示例:
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
foreach语句
foreach的主要作用是遍历一个集合构建in条件。例如,有一个用户List,可以通过foreach遍历List获取所有用户id作为in条件。
foreach标签的属性主要有item,index,collection,open,separator,close。
- item 表示遍历集合时的当前元素(如果集合是map,item是值)
- index 表示遍历集合时的当前元素索引(如果集合是map,item是键)
- open 表示该语句开始字符串
- separator 表示语句中元素之间的分隔符
- close 表示该语句结束字符串
- collection 表示集合的类型,任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数
<select id = "selectUserIn" resultType = "User" parameterType="java.util.List">
SELECT *
FROM User
WHERE id in
<foreach item = "item" index = "index" collection = "list"
open = "(" separator = "," close = ")">
#{item}
</foreach>
</select>
动态sql例子
UserMapper.xml
映射文件中添加如下代码:
...
<select id="getByName" parameterType="User" resultMap="result">
SELECT * FROM User
<if test="name != null">
WHERE name LIKE #{name}
</if>
</select>
...
App.Java
应用程序main类文件中添加如下代码:
...
System.out.println("------------ 动态sql获取用户 -----------");
User user3 = new User("user3");
user3 = (User) session.selectOne("User.getByName", user3);
System.out.println(user3.getId());
System.out.println(user3.getName());
System.out.println("动态sql获取用户成功");
....
运行
输出:
------------ 动态sql获取用户 -----------
3
user3
动态sql获取用户成功