动态sql查询

多条件查询

用if标签

之前我们的多条件查询是在给出所有条件的基础上对数据进行查询。但是如果用户不是输入全部的条件的话,或者只是根据几个数据来匹配一些数据,那么就需要灵活多变。

我们可以用到if标签,我们先用if标签
在sql映射文件中我们这样写

  1. <select id="selectByDynamicCondition" resultMap="brandResultMap">
  2. select *
  3. from tb_brand
  4. where
  5. <if test="status!=null">
  6. status = #{status}
  7. </if>
  8. <if test="companyName!= null and companyName !=''">
  9. and company_name like #{companyName}
  10. </if>
  11. <if test="brandName != null and brandName!=''">
  12. and brand_name like #{brandName}
  13. </if>
  14. </select>

然后接口类中写入

  1. List<Brand> selectByDynamicCondition(Map map);

在测试类中写入

  1. int status = 1;
  2. // 模糊查询
  3. String companyName = "华为";
  4. String brandName = "华为";
  5. // 处理参数
  6. companyName = "%"+companyName+"%";
  7. brandName= "%"+brandName+"%";
  8. //将参数封装对象
  9. // Brand brand = new Brand();
  10. // brand.setStatus(status);
  11. // brand.setCompanyName(companyName);
  12. // brand.setBrandName(brandName);
  13. //// //获取SqlSessionFactory
  14. Map map = new HashMap<>();
  15. map.put("status",status);
  16. // map.put("companyName",companyName);
  17. map.put("brandName",brandName);
  18. String resource = "mybatis-config.xml";
  19. InputStream inputStream = Resources.getResourceAsStream(resource);
  20. SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  21. SqlSession sqlSession = sqlSessionFactory.openSession();
  22. //获取Mapper接口代理对象
  23. BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);
  24. List<Brand> brands = brandMapper.selectByDynamicCondition(map);
  25. System.out.println(brands);

我们没有加入companyName,但是我们还是可以根据已有的条件得到结果。

动态sql查询 - 图1

我们最终在运行时自动拼接到的sql语句为

  1. select * from tb_brand where # where 1=1 status = ? and brand_name like ?

但是需要注意的是,我们注意观察。如果我不添加status条件的话,是会出现问题。什么问题?现在我们不添加status条件然后运行一下,可以看看提示的信息。
动态sql查询 - 图2
截取下来就是

  1. Preparing: select * from tb_brand where and brand_name like ?

我们知道这样拼接后的结果就是一条错误的语句
所以我们不可能得到正确的结果。那么我们还有什么其他的方法解决这种问题

可以添加这么一句写成这样

  1. <select id="selectByDynamicCondition" resultMap="brandResultMap">
  2. select *
  3. from tb_brand
  4. where 1=1
  5. <if test="status!=null">
  6. status = #{status}
  7. </if>
  8. <if test="companyName!= null and companyName !=''">
  9. and company_name like #{companyName}
  10. </if>
  11. <if test="brandName != null and brandName!=''">
  12. and brand_name like #{brandName}
  13. </if>
  14. </select>

然后运行

动态sql查询 - 图3
你看这样运行拼接的sql语句

  1. Preparing: select * from tb_brand where 1=1 and brand_name like ?

对的这样可以解决,但是存在的问题就是如果我的status再次添加上了,这条语句还是会出现问题,所以这样是不太灵活的。我们·尝试下面的方式

用where标签

这个标签比较只能,它的作用就是会动态的替换掉第一个条件前的and。
作用:
替换where关键字
会动态的去掉第一个条件前的 and
如果所有的参数没有值则不加where关键字
那么我们用这个标签的时候,可以给第一个条件加上and。来尝试使用。

  1. -- </select>-->
  2. <select id="selectByDynamicCondition" resultMap="brandResultMap">
  3. select *
  4. from tb_brand
  5. <where>
  6. <if test="status!=null">
  7. and status = #{status}
  8. </if>
  9. <if test="companyName!= null and companyName !=''">
  10. and company_name like #{companyName}
  11. </if>
  12. <if test="brandName != null and brandName!=''">
  13. and brand_name like #{brandName}
  14. </if>
  15. </where>
  16. </select>

我们主要的问题出现在status这个上面。现在我们分别添加和不添加两种状态来运行代码。
测试代码中不添加status

动态sql查询 - 图4

测试代码添加status
动态sql查询 - 图5
看吧完美解决问题。

单条件查询

如果我只给出任意一个条件,当然上面的模式是完全可以满足的。我们只是来说明一下满足一个单条件查询的语法。

明着说就像switch case语句一样。
我们只在sql映射文件中做出说明更改的部分。其他的还是一样的模式。

  1. <select id="selectByConditionSingle" resultMap="brandResultMap">
  2. select *
  3. from tb_brand
  4. where
  5. # choose相当于switch
  6. # when相当于case
  7. <choose> <!--相当于switch-->
  8. <when test="status!=null">
  9. status = #{status}
  10. </when>
  11. <when test="companyName! = null and companyName != ''">
  12. company_name like {companyName}
  13. </when>
  14. <when test="brandName!=null and brandName != ''">
  15. brand_name like # {brandName}
  16. </when>
  17. </choose>
  18. </select>

这次把方法封装到brand对象了。这样也是可以的。
运行
动态sql查询 - 图6
在单条件查询里面,如果我一个条件都没有写。会发生什么?就上诉的代码段。
这里测试代码这里注释掉了。
动态sql查询 - 图7
动态sql查询 - 图8
如果都满足的话,我们还需要留有余地。不然会出现错误。用otherwise是一种办法

  1. <select id="selectByConditionSingle" resultMap="brandResultMap">
  2. select *
  3. from tb_brand
  4. where
  5. # choose相当于switch
  6. # when相当于case
  7. <choose> <!--相当于switch-->
  8. <when test="status!=null">
  9. status = #{status}
  10. </when>
  11. <when test="companyName! = null and companyName != ''">
  12. company_name like {companyName}
  13. </when>
  14. <when test="brandName!=null and brandName != ''">
  15. brand_name like # {brandName}
  16. </when>
  17. <otherwise>1=1</otherwise>
  18. </choose>
  19. </select>

这样的话,至少不会报错。如果你没有添加搜索数据的话,就不出现结果就行了。

动态sql查询 - 图9
然后其实我们还是可以用到智能的where标签

  1. <select id="selectByConditionSingle" resultMap="brandResultMap">
  2. select *
  3. from tb_brand
  4. <where>
  5. # when相当于case
  6. <choose> <!--相当于switch-->
  7. <when test="status!=null">
  8. status = #{status}
  9. </when>
  10. <when test="companyName!= null and companyName != ''">
  11. company_name like #{companyName}
  12. </when>
  13. <when test="brandName!= null and brandName != ''">
  14. brand_name like #{brandName}
  15. </when>
  16. </choose>
  17. </where>
  18. # choose相当于switch
  19. </select>

where标签的智能之处在于可以帮助检查语法的问题。很明显,我让三个条件都没有匹配,然后这个标签会截断后面的语句。

动态sql查询 - 图10