笔记53 Mybatis快速入门(四)
动态SQL
1.if
假设需要对Product执行两条sql语句,一个是查询所有,一个是根据名称模糊查询。那么按照现在的方式,必须提供两条sql语句:listProduct和listProductByName然后在调用的时候,分别调用它们来执行。如下所示:
Product.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6 <mapper namespace="mybatis.pojo"> 7 8 <select id="listProduct1" resultType="Product"> 9 select * from product 10 </select> 11 <select id="listProductByName" resultType="Product"> 12 select * 13 from product where name like concat('%',#{name},'%') 14 </select> 15 </mapper>
Test.java
1 package mybatis.test; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 9 import org.apache.ibatis.session.SqlSession; 10 import org.apache.ibatis.session.SqlSessionFactory; 11 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 12 13 import mybatis.pojo.Product; 14 15 public class testIf { 16 public static void main(String[] args) throws IOException { 17 String resource = "mybatis-config.xml"; 18 InputStream inputStream = org.apache.ibatis.io.Resources.getResourceAsStream(resource); 19 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 20 SqlSession session = sqlSessionFactory.openSession(); 21 22 System.out.println("查询所有的"); 23 List<Product> products = session.selectList("listProduct1"); 24 for (Product product : products) { 25 System.out.println(product); 26 } 27 28 System.out.println("模糊查询"); 29 Map<String, Object> params = new HashMap<String, Object>(); 30 params.put("name", "a"); 31 List<Product> products2 = session.selectList("listProductByName", 32 params); 33 for (Product product : products2) { 34 System.out.println(product); 35 } 36 37 session.commit(); 38 session.close(); 39 } 40 }
如果Product的字段比较多的话,为了应付各个字段的查询,那么就需要写多条sql语句,这样就变得难以维护。这个时候,就可以使用Mybatis 动态SQL里的if标签
1 <select id="listProduct2" resultType="Product"> 2 select * from product 3 <if test="name!=null"> 4 where name like concat('%',#{name},'%') 5 </if> 6 </select>
如果没有传参数name,那么就查询所有,如果有name参数,那么就进行模糊查询。这样只需要定义一条sql语句即可应付多种情况了,在测试的时候,也只需要调用这么一条sql语句listProduct 即可。
1 System.out.println("查询所有的"); 2 List<Product> products = session.selectList("listProduct2"); 3 for (Product product : products) { 4 System.out.println(product); 5 } 6 7 System.out.println("模糊查询"); 8 Map<String, Object> params = new HashMap<String, Object>(); 9 params.put("name", "a"); 10 List<Product> products2 = session.selectList("listProduct2", params); 11 for (Product product : products2) { 12 System.out.println(product); 13 }
2.where
<1>如果要进行多条件判断,如下所示:
1 <select id="listProduct2" resultType="Product"> 2 select * from product 3 <if test="name!=null"> 4 where name like concat('%',#{name},'%') 5 </if> 6 <if test="price!=0"> 7 and price>=#{price} 8 </if> 9 </select>
1 System.out.println("多条件查询"); 2 Map<String, Object> params = new HashMap<String, Object>(); 3 params.put("name", "a"); 4 params.put("price", "10"); 5 List<Product> products2 = session.selectList("listProduct4", params); 6 for (Product product : products2) { 7 System.out.println(product); 8 }
这么写的问题是:当没有name参数,却有price参数的时候,执行的sql语句就会是:select * from product_ and price > 10。这样就会报错。
这个问题可以通过<where>标签来解决,如代码所示:
1 <select id="listProduct4" resultType="Product"> 2 select * from product 3 <where> 4 <if test="name!=null"> 5 and name like concat('%',#{name},'%') 6 </if> 7 <if test="price!=null and price!=0"> 8 and price>#{price} 9 </if> 10 </where> 11 </select>
<where>标签会进行自动判断:
如果任何条件都不成立,那么就在sql语句里就不会出现where关键字
如果有任何条件成立,会自动去掉多出来的 and 或者 or。
所以map里面两个参数无论是否提供值都可以正常执行。
<2>与where标签类似的,在update语句里也会碰到多个字段相关的问题。 在这种情况下,就可以使用set标签:
1 <update id="updateProduct" parameterType="Product"> 2 update product 3 <set> 4 <if test="name!=null">name=#{name},</if> 5 <if test="price!=null">price=#{price}</if> 6 </set> 7 where id=#{id} 8 </update>
1 Product product = new Product(); 2 product.setId(6); 3 product.setName("product xzz"); 4 product.setPrice(6.99f); 5 session.update("updateProduct", product);
<3>trim 用来定制想要的功能,比如where标签就可以用以下代码替换:
1 <trim prefix="WHERE" prefixOverrides="AND |OR "> 2 ... 3 </trim>
set标签可以用以下代码来替换:
1 <trim prefix="SET" suffixOverrides=","> 2 ... 3 </trim>
示例:
1 <select id="listProduct5" resultType="Product"> 2 select * from product 3 <trim prefix="WHERE" prefixOverrides="AND|OR"> 4 <if test="name!=null"> 5 and name like concat('%',#{name},'%') 6 </if> 7 <if test="price!=null and price!=0"> 8 and price>#{price} 9 </if> 10 </trim> 11 </select>
1 <update id="updateProduct2" parameterType="Product"> 2 update product 3 <trim prefix="SET" suffixOverrides=","> 4 <if test="name!=null">name=#{name},</if> 5 <if test="price!=null">price=#{price}</if> 6 </trim> 7 where id=#{id} 8 </update>
3.choose
Mybatis里面没有else标签,但是可以使用when otherwise标签来达到这样的效果。
1 <select id="listProduct6" resultType="Product"> 2 select * from product 3 <where> 4 <choose> 5 <when test="name!=null"> 6 and name like concat('%',#{name},'%') 7 </when> 8 <when test="price!=null and price!=0"> 9 and price>#{price} 10 </when> 11 <otherwise> 12 and id>1 13 </otherwise> 14 </choose> 15 </where> 16 </select>
作用: 提供了任何条件,就进行条件查询,否则就使用id>1这个条件。
1 System.out.println("多条件查询"); 2 Map<String, Object> params = new HashMap<String, Object>(); 3 // params.put("name", "a"); 4 // params.put("price", "10"); 5 List<Product> products2 = session.selectList("listProduct6", params); 6 for (Product products : products2) { 7 System.out.println(products); 8 }
查询结果:
如果去掉注释,提供查询条件,则结果如下:
4.foreach
适用情况如下所示:
1 <select id="listProduct7" resultType="Product"> 2 select * from product 3 where id in 4 <foreach item="item" index="index" collection="list" open="(" 5 separator="," close=")"> 6 #{item} 7 </foreach> 8 </select>
collection :collection属性的值有三个分别是list、array、map三种,分别对应的参数类型为:List、数组、map集合
item : 表示在迭代过程中每一个元素的别名
index :表示在迭代过程中每次迭代到的位置(下标)
open :前缀
close :后缀
separator :分隔符,表示迭代时每个元素之间以什么分隔
测试:
1 List<Integer> idsIntegers = new ArrayList<Integer>(); 2 idsIntegers.add(1); 3 idsIntegers.add(3); 4 idsIntegers.add(5); 5 6 List<Product> products = session.selectList("listProduct7", idsIntegers); 7 8 for (Product product : products) { 9 System.out.println(product); 10 }
结果:
5.bind
bind标签就像是再做一次字符串拼接,方便后续使用。如下所示,在模糊查询的基础上,把模糊查询改为bind标签。
1 <select id="listProductByName" resultType="Product"> 2 select * 3 from product 4 where name like concat('%',#{name},'%') 5 </select>
1 <select id="listProductByName2" resultType="Product"> 2 <bind name="likename" value="'%'+name+'%'"/> 3 select * 4 from product 5 where name like #{likename} 6 </select>