动态sql查询
多条件查询
用if标签
之前我们的多条件查询是在给出所有条件的基础上对数据进行查询。但是如果用户不是输入全部的条件的话,或者只是根据几个数据来匹配一些数据,那么就需要灵活多变。
我们可以用到if标签,我们先用if标签
在sql映射文件中我们这样写
<select id="selectByDynamicCondition" resultMap="brandResultMap">
select *
from tb_brand
where
<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);
//// //获取SqlSessionFactory
Map 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_brand
where 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_brand
where
# 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_brand
where
# 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标签的智能之处在于可以帮助检查语法的问题。很明显,我让三个条件都没有匹配,然后这个标签会截断后面的语句。