MyBatis choose 和 bind
1. 前言
在上一小节中,我们介绍了 MyBatis 动态 SQL 中最基础的标签——if 标签,本小节我们将一起学习 choose 和 bind 标签。
choose 标签是 if 标签的增强版,适用于更加复杂的条件判断逻辑;而bind 标签则可以在 OGNL 上下文环境中新绑定一个变量,供后面的 SQL 使用。
2. 定义
慕课解释:
choose
标签相当于编程语言 if…else 语句,用于动态 SQL 中的多条件判断,是 if 标签的增强版。
bind
标签可以在动态 SQL 中通过 OGNL 表达式来创建一个新的变量绑定到上下文中,供后续的 SQL 使用。
3. 实例
下面是一个融合了 choose 和 bind 标签的实例:
<select id="selectUserByLikeName" resultType="com.imooc.mybatis.model.User">
SELECT * FROM imooc_user
WHERE username LIKE
<choose>
<when test="_databaseId == 'mysql'">
CONCAT('%',#{username},'%')
</when>
<when test="_databaseId == 'postgre'">
'%' || #{username} || '%'
</when>
<otherwise>
<bind name="usernameLike" value="'%' + username + '%'"/>
#{usernameLike}
</otherwise>
</choose>
</select>
通过 choose 标签来判断当前的数据库厂商,如果是 MySQL 数据库,则调用CONCAT
函数来拼接 % 和 username,如果是 PostgreSQL 数据库,则使用操作符||
来拼接,如果是其它类型的数据库,则直接通过 OGNL 表达式来绑定一个新的变量 usernameLike。
在这个例子中,choose 是一个条件选择标签,第一个 when 相当于 if 判断,第二个 when 相当于 else if,最后的 otherwise 相当于 else。比起 if 标签,choose 标签无疑更为易用,适用于同一条件的多次判断逻辑。
4. 实践
4.1 例1. 多条件查询用户
请使用 MyBatis 完成对 imooc_user 表多条件查询用户的功能,如果 id 不为空则直接使用 id 查询用户,否则使用 username 查询用户,如果 username 也为空,则直接查询全部用户。
分析:
按照 MyBatis 的开发模式,需先在 UserMapper.xml 文件中添加多条件查询用户的 select 标签,然后在 UserMapper.java 中添加上对应的方法。
步骤:
首先,在 UserMapper.xml 中添加 select 标签,并在标签中写入 SQL,使用 choose 中的 when 标签来依次判断 id 和 username 是否为 null,若均为 null,则在 otherwise 中添加上一个永假的值。如下:
<select id="selectUserByIdOrName" resultType="com.imooc.mybatis.model.User">
SELECT * FROM imooc_user
WHERE
<choose>
<when test="id != null">
id = #{id}
</when>
<when test="username != null">
username = #{username}
</when>
<otherwise>
1 = 0
</otherwise>
</choose>
</select>
这里使用了1 = 0
作为条件判断的永假值。
然后在 UserMapper.java 中添加上对应的接口方法,方法接受 id 和 username 两个参数,都可为空。
package com.imooc.mybatis.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.imooc.mybatis.model.User;
@Mapper
public interface UserMapper {
User selectUserByIdOrName(@Param("id") Integer id, @Param("username") String username);
}
结果:
通过如下代码,我们运行 selectUserByIdOrName 这个方法。
UserMapper userMapper = session.getMapper(UserMapper.class);
User pedro = userMapper.selectUserByIdOrName(null, null);
System.out.println(pedro);
id 和 username 两个属性均为空,因此所执行的 SQL 为:
SELECT * FROM imooc_user WHERE 1 = 0
成功后,结果为:
null
4.2 例2. 查询小写名称客户
请使用 MyBatis 完成对 imooc_user 表查询小写名称客户的功能,将名称小写后再进行查询。
分析:
同上。
步骤:
首先,在 UserMapper.xml 中添加 select 标签,并在标签中写入 SQL,使用 bind 标签将参数小写化成一个新的变量 lowercaseName。
<select id="selectUsernameLowercase" resultType="com.imooc.mybatis.model.User">
<bind name="lowercaseName" value="username.toLowercase"/>
SELECT * FROM imooc_user
WHERE username = #{lowercaseName}
</select>
然后在 UserMapper.java 中添加上对应的接口方法,方法接受 username 一个参数。
package com.imooc.mybatis.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.imooc.mybatis.model.User;
@Mapper
public interface UserMapper {
User selectUsernameLowercase(String username);
}
结果:
通过如下代码,我们运行 selectUsernameLowercase 这个方法。
UserMapper userMapper = session.getMapper(UserMapper.class);
User pedro = userMapper.selectUsernameLowercase("PEDRO");
System.out.println(pedro);
成功后,结果为:
User{id=2, username='pedro', age=24, score=200}
5. 小结
- bind 标签虽然可以通过 OGNL 表达式在上下文中绑定一个新的变量,但在实际应用所见不多,我们希望在代码层面上处理好参数,这样既方便维护,也更有利于迁移。
- choose 标签是一个增强版的 if 标签,适用于更加复杂的逻辑判断场景。