本文为how2java Mybatis教程的学习笔记,原教程链接如下:http://how2j.cn/k/mybatis/mybatis-tutorial/1087.html#nowhere
if 标签
背景
假设需要对Product执行两条sql语句,一个是查询所有,一个是根据名称模糊查询。那么按照现在的方式,必须提供两条sql语句:listProduct和listProductByName。然后在调用的时候,分别调用它们来执行。如下所示:
Product.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.how2java.pojo">
<select id="listProduct" resultType="Product">
select * from product_
</select>
<select id="listProductByName" resultType="Product">
select * from product_ where name like concat('%',#{name},'%')
</select>
</mapper>
调用:
System.out.println("查询所有的");
List<Product> ps = session.selectList("listProduct");
for (Product p : ps) {
System.out.println(p);
}
System.out.println("模糊查询");
List<Product> ps2 = session.selectList("listProductByName","a");
for (Product p : ps2) {
System.out.println(p);
}
如果Product的字段比较多的话,为了应付各个字段的查询,那么就需要写多条sql语句,这样就变得难以维护。
这个时候,就可以使用Mybatis 动态SQL里的if标签。
使用if标签
Product.xml:
...
<select id="listProduct" resultType="Product">
select * from product_
<if test="name!=null">
where name like concat('%',#{name},'%')
</if>
</select>
...
调用:
System.out.println("查询所有的");
List<Product> ps = session.selectList("listProduct");
for (Product p : ps) {
System.out.println(p);
}
System.out.println("模糊查询");
Map<String,Object> params = new HashMap<>();
params.put("name","a");
List<Product> ps2 = session.selectList("listProduct",params);
for (Product p : ps2) {
System.out.println(p);
}
如果没有传参数name,那么就查询所有,如果有name参数,那么就进行模糊查询。这样只需要定义一条sql语句即可应付多种情况了。
运行结果:
where、 set、 trim 标签
背景
利用if标签,如果要进行多条件判断,就会写成这样:
<select id="listProduct" resultType="Product">
select * from product_
<if test="name!=null">
where name like concat('%',#{name},'%')
</if>
<if test="price!=0">
and price > #{price}
</if>
</select>
这么写的问题是:当没有name参数,却有price参数的时候,执行的sql语句就会是:
select * from product_ and price > 10
这句SQL是有语法错误的(多了一个and),不能执行。
使用where标签
select语句出现的上述问题可以通过where标签来解决:
<select id="listProduct" resultType="Product">
select * from product_
<where>
<if test="name!=null">
and name like concat('%',#{name},'%')
</if>
<if test="price!=null and price!=0">
and price > #{price}
</if>
</where>
</select>
where标签会进行自动判断:
- 如果任何条件都不成立,那么就在sql语句里就不会出现where关键字。
- 如果有任何条件成立,会自动去掉多出来的 and 或者 or。
下面的测试代码无论加不加注释都可以正确执行:
System.out.println("多条件查询");
Map<String,Object> params = new HashMap<>();
//params.put("name","a");
//params.put("price","10");
List<Product> ps2 = session.selectList("listProduct",params);
for (Product p : ps2) {
System.out.println(p);
}
使用set标签
与where标签类似的,在update语句里也会碰到多个字段相关的问题。 在这种情况下,就可以使用set标签:
...
<update id="updateProduct" parameterType="Product" >
update product_
<set>
<if test="name != null">name=#{name},</if>
<if test="price != null">price=#{price}</if>
</set>
where id=#{id}
</update>
...
使用trim标签
trim 用来定制想要的功能,可以替换上面的where标签和set标签。
替换where标签:
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
替换set标签:
<trim prefix="SET" suffixOverrides=",">
...
</trim>
用trim标签的Product.xml:
<select id="listProduct" resultType="Product">
select * from product_
<trim prefix="WHERE" prefixOverrides="AND |OR ">
<if test="name!=null">
and name like concat('%',#{name},'%')
</if>
<if test="price!=null and price!=0">
and price > #{price}
</if>
</trim>
</select>
<update id="updateProduct" parameterType="Product" >
update product_
<trim prefix="SET" suffixOverrides=",">
<if test="name != null">name=#{name},</if>
<if test="price != null">price=#{price}</if>
</trim>
where id=#{id}
</update>
choose、 when、 otherwise 标签
Mybatis里面没有else标签,但是可以使用choose when otherwise标签来达到if else的效果。
...
<select id="listProduct" resultType="Product">
SELECT * FROM product_
<where>
<choose>
<when test="name != null">
and name like concat('%',#{name},'%')
</when>
<when test="price !=null and price != 0">
and price > #{price}
</when>
<otherwise>
and id >1
</otherwise>
</choose>
</where>
</select>
...
上述代码的效果是: 如果提供了任何条件,就进行条件查询,否则就使用id>1这个条件。
foreach 标签
foreach标签通常用于in 这样的语法里
<select id="listProduct" resultType="Product">
SELECT * FROM product_
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
测试代码:
List<Integer> ids = new ArrayList();
ids.add(1);
ids.add(3);
ids.add(5);
List<Product> ps = session.selectList("listProduct",ids);
for (Product p : ps) {
System.out.println(p);
}
把类似如下sql:select * from product_ where id in (‘1’,’3’,’5’)中in 后面的 (‘1’,’3’,’5’)拆成open=”(” separator=”,” close=”)”这种写法,open=’(‘代表in后面的开始的括号,close=’)’代表结束的括号,而seperator=’,’则代表括号里面数据的分隔符,那么具体的1,3,5则用占位符#{item}进行替换。
bind 标签
bind标签就像是再做一次字符串拼接,方便后续使用。
原来的模糊查询:
<select id="listProduct" resultType="Product">
select * from product_ where name like concat('%',#{0},'%')
</select>
使用bind标签的模糊查询:
<select id="listProduct" resultType="Product">
<bind name="likename" value="'%' + name + '%'" />
select * from product_ where name like #{likename}
</select>