动态sql即可以根据条件动态地执行不同的sql语句,mybatis是通过在mapper.xml中添加逻辑判断来实现动态sql的,逻辑判断的标签主要有<if>
、<choose>
、<when>
、<otherwise>
等。
if标签
动态sql语句通常的表现就是判断sql语句中where子句部分,例如:
<select id="selByAccinAccout" resultType="log">
select * from log where 1=1
<!-- OGNL表达式,直接写key或对象的属性.不需要添加任何特字符号 -->
<if test="accin!=null and accin!=''">
and accin=#{accin}
</if>
<if test="accout!=null and accout!=''">
and accout=#{accout}
</if>
</select>
上述sql语句的where子句中的“1=1”是恒定成立的,在这的作用是为了在两个if判断都不成立的时候,sql语句不报错。
当两个if判断都成立的时候sql语句的执行如下,where中的两个条件都会生效:
当两个if都不成立的时候该sql语句的where子句将只有条件“1=1”,即会查询出所有的记录:
where标签
上述示例sql语句中的where关键字也可以用where标签替代,如果where标签中的内容中第一个是and,sql语句映射将会去掉第一个and,并且只有在where标签中有内容的时候才会生成where关键字,当where标签中没有内容的时候不会生成关键字,这样就不在需要书写“where 1=1”来避免sql语句错误了,例如:
<select id="selByAccinAccout" resultType="log">
select * from log
<where>
<if test="accin!=null and accin!=''">
and accin=#{accin}
</if>
<if test="accout!=null and accout!=''">
and accout=#{accout}
</if>
</where>
</select>
当只传入了accin的时候,执行的sql语句如下:
当只传入了accout的时候,执行的sql语句如下:
当参数accin和accout均传入的时候,执行的sql语句如下:
当参数accin和accout均没有被传入的时候,既不会生成where子句,执行的sql语句如下:
choose、when、otherwise标签
上面的例子中,是当所有的条件都执行的时候,所有的条件都会执行,但有时候我们并不想执行所有的条件,所以我们可以组合使用这三个标签,只要有一个条件成立则会其他的条件都不会执行,例如:
<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>
<otherwise>
and accin='abcd'
</otherwise>
</choose>
</where>
</select>
当两个when标签的条件都成立的时候,执行的sql语句如下:
因为accin的判断在前,所以当accin判断条件成立的时候,accout的判断尽管条件成立也没有执行。
当只有accout判断成立,即只传入accout参数的时候,执行的sql语句如下:
当两个when标签不成立的时候,将会执行otherwise标签的内容构成where子句:
set标签
update标签中使用set标签可以自动去掉最后一列条件的逗号,如果set标签中有内容sql语句映射则会生成set关键字,没有则不会生成set关键字。
<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>
子句“where id=#{id}”是为了避免set标签中没有内容不生成set标签。
trim标签
trim标签主要是用于对sql语句进行裁剪,在sql语句(字符串)中增加、删减或替换字符。trim标签中,prefix属性表示在前面添加内容,prefixOverrides属性表示去掉前面内容,suffix属性表示在后面添加内容,suffixOverrieds属性表示去掉后面内容。
<select id="selByLog" parameterType="log" resultType="log">
select * from log
<trim >abc</trim>
</select>
执行的sql语句为:
添加prefix元素:
<select id="selByLog" parameterType="log" resultType="log">
select * from log
<trim prefix="abc" >abc</trim>
</select>
将会在“abc”的前面再增加一个“abc”,生成的sql语句将报错:
单独使用prefixOverrides元素:
<select id="selByLog" parameterType="log" resultType="log">
select * from log
<trim prefixOverrides="abc">abc</trim>
</select>
生成的sql语句将会去掉“abc”,sql语句正确执行:
同时使用prefix元素和prefixOverrides元素:
<select id="selByLog" parameterType="log" resultType="log">
select * from log
<trim prefix="abc" prefixOverrides="abc">abc</trim>
</select>
去掉了一个“abc”又增加了一个“abc”,所以生成的sql语句中还存在一个“abc”:
bind标签
bind标签中,value对应传入实体类的某个字段,体类中需要该字段有相应的getter方法,name属性既给对应字段取的变量名。在value属性中可以使用字符串拼接等特殊处理。
<select id="selByLog" parameterType="log" resultType="log">
<bind name="accin" value="'%'+accin+'%'"/>
select * from log where accin like
#{accin}
</select>
foreach标签
用于循环传入参数的内容,还具备在内容的前后添加内容,还具备添加分隔符功能。常用在IN条件语句和批量插入中。
<insert id="ins" parameterType="list">
insert into log values
<trim suffixOverrides=",">
<foreach collection="list" item="log">
(default,#{log},2,2),
</foreach>
</trim>
</insert>
<select id="selIn" parameterType="list" resultType="log">
select * from log where id in
<foreach collection="list" item="abc" open="(" close=")" separator=",">
#{abc}
</foreach>
</select>
调用代码:
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//批量插入需指定底层JDBC 的PreparedStatement.addBatch();
SqlSession session = factory.openSession(ExecutorType.BATCH);
LogMapper mapper = session.getMapper(LogMapper.class);
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
list.add(i);
}
mapper.ins(list);
mapper.selIn(list);
session.commit();
session.close();
System.out.println("程序执行结束");
sql标签和include标签
如果某些sql语句片段希望复用,可以使用sql标签定义,然后再通过include标签引用。
<sql id="mysql">
id,accin,accout,money
</sql>
<select id="">
select <include refid="mysql"></include>
from log
</select>