动态SQL
- 根据不同的条件需要执行不同的 SQL 命令,称为动态 SQL
- MyBatis 中动态 SQL 在 mapper.xml 中添加逻辑判断等
mapper.xml文件对应的接口文件:
package com.bjsxt.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.bjsxt.pojo.Log;
public interface LogMapper {
List<Log> selByAccinAccout(@Param("accout") String accout, @Param("accin") String accin);
int upd(Log log);
List<Log> selByLog(Log log);
List<Log> selIn(List<Integer> list);
int ins(List<Integer> list);
}
if 标签
<select id="selByAccinAccout" resultType="log"> <!-- 同样的,resultType为一行的返回类型 -->
select * from log where 1=1 <!-- where后边的1=1是防止生成的sql语句语法错误(and引起) -->
<!-- OGNL 表达式,直接写 key 或对象的属性.不需要添加任何特殊符号 -->
<if test="accin!=null and accin!=''">
<!-- if标签中的test属性中条件满足,生成的sql语句中才会有下边的and ... -->
and accin=#{accin}
</if>
<if test="accout!=null and accout!=''">
and accout=#{accout}
</if>
</select>
where标签
- 当编写 where 标签时,如果内容中开头是 and,则会去掉第一个and(不用再写1=1)
- 如果中有内容会生成 where 关键字,如果没有内容不生成 where 关键字
- 使用示例
- 比直接使用少写 where 1=1
<select id="selByAccinAccout" resultType="log">
select * from log
<where> <!-- 有内容会自动添加where -->
<if test="accin!=null and accin!=''">
and accin=#{accin} <!-- 并且如果语句开头是and,会自动去掉and -->
</if>
<if test="accout!=null and accout!=''">
and accout=#{accout}
</if>
</where>
</select>
choose,when,otherwise标签
- 只有有一个成立,其他都不执行
- 代码示例
- 如果 accin 和 accout 都不是 null 或不是””空串,生成的sql 中只有 where accin=?
<select id="selByAccinAccout" resultType="log">
select * from log
<where>
<choose>
<when test="accin!=null and accin!=''">
and accin=#{accin}
</when>
<when test="accout!=null and accout!=''">
and accout=#{accout}
</when>
</choose>
</where>
</select>
set 标签
用在修改(update) SQL 中 set 从句
- 作用:去掉最后一个逗号
- 作用:如果里面有内容则会生成 set 关键字,没有就不生成
- 示例
- id=#{id} 目的防止中没有内容,mybatis 不生成 set 关键字
- 如果修改中没有 set 从句,那么会有 SQL 语法错误
<update id="upd" parameterType="log" >
update log
<set>
id=#{id},
<if test="accIn!=null and accIn!=''">
accin=#{accIn},
</if>
<if test="accOut!=null and accOut!=''">
accout=#{accOut},
</if>
</set>
where id=#{id}
</update>
trim 标签
-
prefix 在前面添加内容
-
prefixOverrides 去掉前面内容
-
suffix 在后面添加内容
-
suffixOverrides 去掉后面内容
-
注意:执行顺序为:先去掉内容,后添加内容(如where中,如果先添加where,那么第一个就不是and了,而原本要去掉的and也就不会自动去掉)
-
代码示例 (trim模拟set功能)
<update id="upd" parameterType="log">
update log
<trim prefix="set" suffixOverrides=",">
<!-- 注意:这里在前边加上set之后在set后边会多一个空格,精确控制值可以使用下边的bind标签 -->
a=a,
</trim>
where id=100
</update>
bind 标签
- 作用:给参数重新赋值
- 场景:
- 模糊查询
- 在原内容前边或者后边添加内容
<select id="selByLog" parameterType="log" resultType="log">
<bind name="accin" value="'%'+accin+'%'"/> <!-- 传进来的参数为Log对象,accin为对象属性 -->
<!-- 而value把accin属性的值替换 -->
#{...}
</select>
foreach 标签
-
循环参数内容,还具备在内容的前后添加内容,并且还具备添加分隔符功能
-
适用场景:in 查询中,批量新增中(mybatis 中 foreach 效率比较低)
-
如果希望批量新增,SQL 命令
insert into log
values(default,1,2,3),(default,2,3,4),(default,3,4,5);
那么openSession()必须指定:
底层 JDBC 的PreparedStatement.addBatch();
factory.openSession(ExecutorType.BATCH);
-
foreach标签的属性:
- collection=”” 表示要遍历的集合(一般为传进来的参数)
- item 迭代的变量(类比jstl中foreach的var), #{迭代变量名}获取内容
- open 循环后左侧添加的内容 (注意,是整个循环结果之前)
- close 循环后右侧添加的内容 (注意,是整个循环结果之后)
- separator 每次循环时,元素之间的分隔符 (注意,是单次循环结果之后)
-
示例
<select id="selIn" parameterType="list" resultType="log">
select * from log where id in
<foreach collection="list" item="abc" open="(" close=")" separator=",">
#{abc} <!-- 输出结果为集合list中的所有元素的遍历例如Integer泛型的集合:(4,3,2) -->
</foreach>
</select>
sql,include 标签
- 某些 SQL 片段如果希望复用,可以使用定义这个片段
<sql id="mysql"> <!-- 复用块 -->
id,accin,accout,money
</sql>
- 在或或或中使用引用
<select id="">
select
<include refid="mysql"></include>
from log
</select>