动态sql查询
多条件查询
用if标签
之前我们的多条件查询是在给出所有条件的基础上对数据进行查询。但是如果用户不是输入全部的条件的话,或者只是根据几个数据来匹配一些数据,那么就需要灵活多变。
我们可以用到if标签,我们先用if标签
在sql映射文件中我们这样写
<select id="selectByDynamicCondition" resultMap="brandResultMap">select *from tb_brandwhere<if test="status!=null">status = #{status}</if><if test="companyName!= null and companyName !=''">and company_name like #{companyName}</if><if test="brandName != null and brandName!=''">and brand_name like #{brandName}</if></select>
然后接口类中写入
List<Brand> selectByDynamicCondition(Map map);
在测试类中写入
int status = 1;// 模糊查询String companyName = "华为";String brandName = "华为";// 处理参数companyName = "%"+companyName+"%";brandName= "%"+brandName+"%";//将参数封装对象// Brand brand = new Brand();// brand.setStatus(status);// brand.setCompanyName(companyName);// brand.setBrandName(brandName);//// //获取SqlSessionFactoryMap map = new HashMap<>();map.put("status",status);// map.put("companyName",companyName);map.put("brandName",brandName);String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession = sqlSessionFactory.openSession();//获取Mapper接口代理对象BrandMapper brandMapper = sqlSession.getMapper(BrandMapper.class);List<Brand> brands = brandMapper.selectByDynamicCondition(map);System.out.println(brands);
我们没有加入companyName,但是我们还是可以根据已有的条件得到结果。

我们最终在运行时自动拼接到的sql语句为
select * from tb_brand where # where 1=1 status = ? and brand_name like ?
但是需要注意的是,我们注意观察。如果我不添加status条件的话,是会出现问题。什么问题?现在我们不添加status条件然后运行一下,可以看看提示的信息。
截取下来就是
Preparing: select * from tb_brand where and brand_name like ?
我们知道这样拼接后的结果就是一条错误的语句
所以我们不可能得到正确的结果。那么我们还有什么其他的方法解决这种问题
可以添加这么一句写成这样
<select id="selectByDynamicCondition" resultMap="brandResultMap">select *from tb_brandwhere 1=1<if test="status!=null">status = #{status}</if><if test="companyName!= null and companyName !=''">and company_name like #{companyName}</if><if test="brandName != null and brandName!=''">and brand_name like #{brandName}</if></select>
然后运行

你看这样运行拼接的sql语句
Preparing: select * from tb_brand where 1=1 and brand_name like ?
对的这样可以解决,但是存在的问题就是如果我的status再次添加上了,这条语句还是会出现问题,所以这样是不太灵活的。我们·尝试下面的方式
用where标签
这个标签比较只能,它的作用就是会动态的替换掉第一个条件前的and。
作用:
替换where关键字
会动态的去掉第一个条件前的 and
如果所有的参数没有值则不加where关键字
那么我们用这个标签的时候,可以给第一个条件加上and。来尝试使用。
-- </select>--><select id="selectByDynamicCondition" resultMap="brandResultMap">select *from tb_brand<where><if test="status!=null">and status = #{status}</if><if test="companyName!= null and companyName !=''">and company_name like #{companyName}</if><if test="brandName != null and brandName!=''">and brand_name like #{brandName}</if></where></select>
我们主要的问题出现在status这个上面。现在我们分别添加和不添加两种状态来运行代码。
测试代码中不添加status

测试代码添加status
看吧完美解决问题。
单条件查询
如果我只给出任意一个条件,当然上面的模式是完全可以满足的。我们只是来说明一下满足一个单条件查询的语法。
明着说就像switch case语句一样。
我们只在sql映射文件中做出说明更改的部分。其他的还是一样的模式。
<select id="selectByConditionSingle" resultMap="brandResultMap">select *from tb_brandwhere# choose相当于switch# when相当于case<choose> <!--相当于switch--><when test="status!=null">status = #{status}</when><when test="companyName! = null and companyName != ''">company_name like {companyName}</when><when test="brandName!=null and brandName != ''">brand_name like # {brandName}</when></choose></select>
这次把方法封装到brand对象了。这样也是可以的。
运行
在单条件查询里面,如果我一个条件都没有写。会发生什么?就上诉的代码段。
这里测试代码这里注释掉了。

如果都满足的话,我们还需要留有余地。不然会出现错误。用otherwise是一种办法
<select id="selectByConditionSingle" resultMap="brandResultMap">select *from tb_brandwhere# choose相当于switch# when相当于case<choose> <!--相当于switch--><when test="status!=null">status = #{status}</when><when test="companyName! = null and companyName != ''">company_name like {companyName}</when><when test="brandName!=null and brandName != ''">brand_name like # {brandName}</when><otherwise>1=1</otherwise></choose></select>
这样的话,至少不会报错。如果你没有添加搜索数据的话,就不出现结果就行了。

然后其实我们还是可以用到智能的where标签
<select id="selectByConditionSingle" resultMap="brandResultMap">select *from tb_brand<where># when相当于case<choose> <!--相当于switch--><when test="status!=null">status = #{status}</when><when test="companyName!= null and companyName != ''">company_name like #{companyName}</when><when test="brandName!= null and brandName != ''">brand_name like #{brandName}</when></choose></where># choose相当于switch</select>
where标签的智能之处在于可以帮助检查语法的问题。很明显,我让三个条件都没有匹配,然后这个标签会截断后面的语句。

