说明
模糊查询在项目中还是经常使用的,本文就简单整理Mybatis中使用Like进行模糊查询的几种写法以及一些常见的问题。
使用Springboot简单配置一下Mybatis,然后进行说明。Springboot集成Mybatis这里就不做介绍了,这里我们主要介绍一下在mybatis配置文件中怎么使用模糊查询。
本地表数据
具体方式
方式一
在Mybatis中的写法:
<select id="queryLists" parameterType="java.lang.String" resultMap="BaseResultMap">
select * from stuinfo
where 1=1
<if test="name != null and name != ''">
AND name like '%${name}%'
</if>
order by id desc
</select>
输出以下语句:
这种会有sql注入的问题,需要明白在 Mybatis中 $ 和 # 使用的区别。这种写法也不能加jdbcType=VARCHAR,否则也会报错。
注意:这种方式在实际开发过程中千万要注意,不要写成这样了。
方式二
在Mybatis中的写法:
<select id="queryLists" parameterType="java.lang.String" resultMap="BaseResultMap">
select * from stuinfo
where 1=1
<if test="name != null and name != ''">
AND name like #{name,jdbcType=VARCHAR}
</if>
order by id desc
</select>
在代码中加上%
@GetMapping("/lists")
@ResponseBody
public List<StuInfo> lists(String name){
return stuInfoService.getLists('%'+name+'%');
}
输出以下语句:
这种方式在一些项目中也会看到。如果没有使用如Mybatis等ORM框架,直接写sql查询就这样拼接了。
第一种方式和第二种方式基本上一致
方式三
在Mybatis中的写法:
<select id="queryLists" parameterType="java.lang.String" resultMap="BaseResultMap">
select * from stuinfo
where 1=1
<if test="name != null and name != ''">
AND name like concat('%', #{name}, '%')
</if>
order by id desc
</select>
输出以下语句:
说明:在实际开发中推荐使用这种方式。
方式四
在Mybatis中的写法:
<select id="queryLists" parameterType="java.lang.String" resultMap="BaseResultMap">
select * from stuinfo
where 1=1
<if test="name != null and name != ''">
and POSITION(#{name} IN name) > 0
</if>
order by id desc
</select>
以上写法是在postgresql中的函数:POSITION(#{name} IN name) 在mysql中 请使用: INSTR(name, #{name}) > 0
输出以下语句:
需要注意
当使用方式三的时候,如果查询的关键字就是%, get 请使用%25 url编码 ,那情况会就会变成什么呢! 初始化数据中name有6条数据中包含%。
查询的sql如下:
select * from stuinfo where name like concat('%','%','%')
查出来全部的数据,并不是只包含了%的数据,如果查询也是一样的。
那这种情况肯定是不满足查询需求的,则需要调整。
解决以上问题
代码中处理:
@GetMapping("/lists")
@ResponseBody
public List<StuInfo> lists(String name){
name = name.replaceAll("_", "\\\\_");
name = name.replaceAll("%", "\\\\%");
return stuInfoService.getLists(name);
}
在Mybatis中的写法:
<select id="queryLists" parameterType="java.lang.String" resultMap="BaseResultMap">
select * from stuinfo
where 1=1
<if test="name != null and name != ''">
AND name like concat('%',#{name,jdbcType=VARCHAR},'%') ESCAPE '\'
</if>
order by id desc
</select>
输出以下语句:
以上两种本质都是对查询的关键字进行了处理,这种处理在代码中可以使用拦截器或者AOP等技术统一处理。
总结
1、不要写方式一的这种模糊查询,容易发生sql注入!
建议使用第三种方式进行模糊查询
2、上面这前三种模糊查询,都是使用%关键字%,这种方式是不会走索引的,大数据量时候有查询效率低,第四中使用字符串包含函数。
看情况,可以使用全文索引;或者使用ES进行
3、注意关键词中有%、_ 这些特殊字符如何处理。
1、业务上不允许输入这些字符,需要通过(前台、后台)进行过滤。
2、使用上面的ESCAPE或者转义。