通过if标签构建动态条件,通过其test属性的true或false来判断该添加语句是否执行。
mapper接口
public interface AccountMapper {
List<Account> selectAllByCondition(Account account);
}
映射文件
<select id="selectAllByCondition" resultMap="AccountMap">
select *
from account
where 1=1
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="accountType!=null and accountType!=''">
and account_type=#{accountType}
</if>
</select>
这里test中的属性名与Account类中的属性名一致。例如:上述文件的第一个if标签中的id严格与Account中属性名id一致。
测试
@Test
public void sqlTest(){
AccountMapper accountMapper = sqlSession.getMapper(AccountMapper.class);
Account account=new Account();
account.setId(1);
account.setAccountType("Checking");
List<Account> accounts = accountMapper.selectAllByCondition(account);
System.out.println(accounts);
}
结果:
执行效果等同于select * from account where 1=1 and id=1 and account_type="Checking"
现在修改查询的id属性值,将其赋值为空,在测试类中注释掉account.setId方法
test属性是boolean类型,通过表达式判断true,false,决定此条件是否会被执行
注意其中的1=1,这样就可以解决if标签可能会带来的sql语法错误例如:
select * from account where and id=1;
当Mapper接口传递的是@Param参数指定的形参时,if标签中的test属性名应与Param参数指定的值一致
例如接口参数修改为如下形式:
public interface AccountMapper {
List<Account> selectAllByCondition(@Param("AccountId") int id,@Param("accountType") String accountType);
}
映射文件应修改如下(注意AccountId的修改):
<select id="selectAllByCondition" resultMap="AccountMap">
select *
from account
where 1=1
<if test="AccountId!=null and AccountId!=''">
and id=#{AccountId}
</if>
<if test="accountType!=null and accountType!=''">
and account_type=#{accountType}
</if>
</select>
这中映射规则与#{}值的映射类似
where标签是对if标签的升级版,这里用where标签替代where语句,而且它还能消除条件语句中可能出现的多余sql字段,例如and,or。
映射文件修改如下:
<select id="selectAllByCondition" resultMap="AccountMap">
select *
from account
<where>
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="accountType!=null and accountType!=''">
and account_type=#{accountType}
</if>
</where>
</select>
这里测试时id为null,此时where语句会自动去除if标签中属性值前多余的and或者or,如果and或or在属性值后面则不会生效。
使用trim标签可以添加在指定sql语句前添加删除字段
映射文件修改
<select id="selectAllByCondition" resultMap="AccountMap">
select *
from account
<trim prefix="where" prefixOverrides="and">
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="accountType!=null and accountType!=''">
and account_type=#{accountType}
</if>
</trim>
</select>
测试结果
当测试id值为null时,prefixOverrides属性值的设定取出了多余的and,prefix值的设定在trim标签前添加了where。如下,trim标签还用suffix,suffixOverrides属性,与前两个属性相对,分别是在trim标签中语句后添加值,在if标签中对and或or相对属性值后的动态处理,防止sql语句出错。
如下choose标签中的when,otherwise类似与if else,它只会执行其中的一个
<select id="selectAllByCondition" resultMap="AccountMap">
select *
from account
where
<choose>
<when test="id!=null and id!=''">
id=#{id}
</when>
<otherwise>
account_type=#{accountType}
</otherwise>
</choose>
</select>
测试方法中只设置id属性
@Test
public void sqlTest(){
AccountMapper accountMapper = sqlSession.getMapper(AccountMapper.class);
Account account=new Account();
account.setId(2);
// account.setAccountType("Checking");
List<Account> accounts = accountMapper.selectAllByCondition(account);
System.out.println(accounts);
}
结果:
再将id属性设置注释掉,测试
它只会执行其中一个条件,而且一定会执行其中一个。
foreach标签是针对于集合,列表的类似与for循环
范围查询:
接口方法:
List<Account> selectByIds(@Param("ids") int [] s);
映射文件
<select id="selectByIds" resultMap="AccountMap">
select * from account where id in(1,2);
</select>
测试
@Test
public void sqlTest2(){
AccountMapper accountMapper = sqlSession.getMapper(AccountMapper.class);
int [] ids={1,2};
List<Account> accounts = accountMapper.selectByIds(ids);
System.out.println(accounts);
}
修改xml,使用foreach标签
<select id="selectByIds" resultMap="AccountMap">
select * from account where id in(
<foreach collection="ids" item="id" separator=",">
id
</foreach><!--遍历ids数组,将生成的id以,隔开-->
);
</select>
结果