<if>元素
<if>元素是简单的条件判断,可用来实现某些简单的条件选择,书上举的例子是:当输入查询条件是,按条件模糊查询用户名,当什么都没输入时,查询所有用户名。我先说步骤,再说我的看法吧。
1.在UsrInfoMapper.xml映射文件中配置select语句块
<!--动态SQL之<if>元素 -->
<select id="findUserInfoUserNameWithIf" parameterType="userInfo" resultType="UserInfo">
select * from user_info ui
<if test="userName!=null and userName!=''">
where ui.userName LIKE CONCAT(CONCAT('%',#{userName}),'%')
</if>
</select>
2.创建接口并声明方法
package com.mybatis.mapper;
import java.util.List;
import com.mybatis.pojo.UserInfo;
public interface UserInfoMapper {
List<UserInfo> findUserInfoUserNameWithIf(UserInfo ui);
}
3.写测试方法
@Test
public void testFindUserInfoUserNameWithIf() {
UserInfoMapper uim = sqlSession.getMapper(UserInfoMapper.class);
UserInfo ui = new UserInfo();
ui.setUserName("j");//后面注释掉这行做测试
List<UserInfo> list = uim.findUserInfoUserNameWithIf(ui);
for (UserInfo uInfo : list) {
System.out.println(uInfo.toString());
}
}
4.先测试正常设置了查询值的时候
再测试没有设置查询值的情况,也就是注释掉那行代码做测试
发现sql语句少了where的部分,查询的是全部用户
我是这么想的,在接受到表单数据时,加个if判断他不香吗?还能多写几种条件。
<where> <if>元素
当<if>元素较多时,可能会拼装成 where and 或者 where or 之类的关键字多余的错误SQL语句,这时候就应该用到<where>元素。
1.在UsrInfoMapper.xml映射文件中配置select语句块
<!--动态SQL之<where>元素 -->
<select id="findUserInfoByUserNameAndStatus" parameterType="UserInfo" resultType="UserInfo">
select * from user_info ui
<where>
<if test="userName!=null and userName!=''">
ui.userName LIKE CONCAT(CONCAT('%',#{userName}),'%')
</if>
<if test="status>-1">
and ui.status = #{status}
</if>
</where>
</select>
2.创建接口并声明方法
3.写测试方法,主要测试以下几种情况
都输入了值时
当设置status值为-1时
当没有输入姓名查询条件时
<set> <if>元素
<set> 和 <if>元素可用来组装update语句,只有当<set>元素内的条件成立时,才会在组装SQL语句时加上set关键字.<set>元素内包含了<if>子元素,每个<if>元素包含的SQL后面会有一个逗号,拼接好的SQL语句中会包含多余的逗号,从而造成SQL语法错误,不过<set>元素能将SQL语句中的多余逗号剔除。
<!--动态SQL之<set><if>元素 -->
<update id="updateUserInfo" parameterType="UserInfo">
update user_info ui
<set>
<if test="userName!=null and userName!=''">
ui.userName = #{userName},
</if>
<if test="password!=null and password!=''">
ui.password = #{password}
</if>
</set>
where ui.id=#{id}
</update>
@Test
public void testUpdateUserInfo() {
UserInfoMapper uim = sqlSession.getMapper(UserInfoMapper.class);
UserInfo ui = new UserInfo();
ui.setId(3);
//ui.setUserName("fzj");
ui.setPassword("123");
uim.updateUserInfo(ui);
}
测试以下情形
都输入了值
没有输用户名
没有输密码
id肯定要输的,毕竟不再if里,还是试一下
我以为他会报错,说少传一个参数,但还是修改了,默认修改第0个,而表是从第一个开始,就相当于是没修改。
<trim>元素
使用<trim>元素,可以通过prefix属性在要拼装的SQL语句片段前加上前缀,通过suffix属性在要拼装的SQL语句片段之后加上后缀,通过prefixOverrides属性把要拼装的SQL语句片段首部的某些内容覆盖,通过suffixOverrides属性把要拼装的SQL语句片段尾部的某些内容覆盖。因此<trim>元素可用来替代<where>元素和<set>元素实现同样的功能。
使用<trim>元素替代<where>元素,从数据表user_info中按用户名模糊查询,同时查询指定状态的用户列表,实现步骤如下所示。
1.编写映射文件
<!--动态SQL之<trim>元素 -->
<select id="findUserInfoByUserNameWithIf_Trim" parameterType="UserInfo" resultType="UserInfo">
select * from user_info ui
<trim prefix="where" prefixOverrides="and|or">
<if test="userName!=null and userName!=''">
ui.userName LIKE CONCAT(CONCAT('%',#{userName}),'%')
</if>
<if test="status>-1">
and ui.status = #{status}
</if>
</trim>
</select>
prefix属性设置为where,将要拼装的SQL语句的前缀设置为where,即要使用where关键字来连接后面的SQL语句片段;prefixOverrides属性设置为and|or,是将要拼装的SQL语句片段首部多余的“and”或“or”关键字去除
接口
测试方法
@Test
public void testFindUserInfoByUserNameWithIf_Trim() {
UserInfoMapper uim = sqlSession.getMapper(UserInfoMapper.class);
UserInfo ui = new UserInfo();
ui.setUserName("j");
ui.setStatus(1);
List<UserInfo> list = uim.findUserInfoByUserNameWithIf_Trim(ui);
for (UserInfo userInfo : list) {
System.out.println(userInfo.toString());
}
}
运行结果和where,if的一样
接下来演示替代<set>
<!--动态SQL之<trim>元素<set>元素 -->
<update id="updateUserInfo_trim" parameterType="UserInfo">
update user_info ui
<trim prefix="set" suffixOverrides=",">
<if test="userName!=null and userName!=''">
ui.userName = #{userName},
</if>
<if test="password!=null and password!=''">
ui.password = #{password}
</if>
</trim>
where ui.id=#{id}
</update>
后续步骤省略。运行结果和<set>一样
<choose>、<when>和<otherwise>元素
在查询中,如果不想使用所有的条件,而只是想从多个选项中选择一个,可以使用MyBatis提供的<choose>、<when>和<otherwise>元素来实现。<choose>元素会按顺序判断<when>元素中的条件是否成立,如果有一个成立,则不再判断后面<when>元素中的条件是否成立,<choose>元素执行结束;如果所有<when>的条件都不满足,则执行<otherwise>元素中的SQL语句。
如果想从数据表user_info中根据userName或status进行查询,当userName不为空时则只按照userName查询,其他条件忽略;否则当status大于-1时,则只按照status查询;当userName和status都为空时,则查询所有用户记录,使用<choose>、<when>和<otherwise>元素实现这个示例的步骤如下所示。
<!--动态SQL之<choose>、<when>和<otherwise>元素 -->
<select id="findUserInfo_Choose" parameterType="UserInfo" resultType="UserInfo">
select * from user_info ui
<where>
<choose>
<when test="userName!=null and userName!=''">
ui.userName LIKE CONCAT(CONCAT('%',#{userName}),'%')
</when>
<when test="status>-1">
and ui.status = #{status}
</when>
<otherwise>
</otherwise>
</choose>
</where>
</select>
后续流程还是上面那一套,运行结果也一样,毕竟是替代嘛。
<foreach>元素
<foreach>元素主要是迭代一个集合,通常是用于in条件。例如SQL中的条件形如:where id in(一大串的id),这时可使用<foreach>元素,而不必去拼接id字符串。
<foreach>元素可以向SQL语句传递数组、List<E>等实例。List<E>实例使用list做为键,数组实例使用array做为键。
如果想从数据表user_info中查询id为1和3的用户记录,使用<foreach>元素的List实例的实现步骤如下所示。
<!--动态SQL之<foreach>元素,使用List<E>实例 -->
<select id="findUserInfoByIds" resultType="UserInfo">
select * from user_info ui where ui.id in
<foreach collection="list" item="ids" open="(" close=")" separator=",">
#{ids}
</foreach>
</select>
有以下几点要说明
item属性表示集合中每个元素迭代时的别名
open表示该语句的开始符号,separator表示每次迭代之间的分隔符号,close表示该语句结束符号
collections属性根据具体情况选择list或array
上面这个是<foreach>的List<E>实例的实现步骤
下面试一下arrea实例的实现
<!--动态SQL之<foreach>元素,使用array实例 -->
<select id="findUserInfoByIds2" resultType="UserInfo">
select * from user_info ui where ui.id in
<foreach collection="array" item="ids" open="(" close=")" separator=",">
#{ids}
</foreach>
</select>
@Test
public void testFindUserInfoByIds2() {
UserInfoMapper uim = sqlSession.getMapper(UserInfoMapper.class);
//创建集合对象ids,保存用户id
int[] ids = new int[2];
ids[0]=1;
ids[1]=2;
List<UserInfo> userInfos=uim.findUserInfoByIds2(ids);
for (UserInfo userInfo : userInfos) {
System.out.println(userInfo.toString());
}
}