MyBatis模糊查询:LIKE语句的正确使用与进阶实践
2025.09.19 15:54浏览量:1简介:本文深入解析MyBatis中LIKE模糊查询的多种实现方式,涵盖基础语法、参数绑定、防SQL注入方案及性能优化技巧,帮助开发者掌握安全高效的模糊查询实践。
MyBatis模糊查询:LIKE语句的正确使用与进阶实践
在MyBatis框架中进行模糊查询时,LIKE语句的正确使用直接关系到查询效率与系统安全性。本文将从基础语法到高级实践,系统讲解五种实现方式及其适用场景,帮助开发者规避常见陷阱。
一、基础语法实现
1.1 字符串拼接(不推荐)
<!-- 错误示范:直接拼接字符串 -->
<select id="findByName" resultType="User">
SELECT * FROM user WHERE name LIKE '%${name}%'
</select>
风险分析:
这种写法存在SQL注入漏洞,当name
参数为' OR '1'='1
时,会生成WHERE name LIKE '%' OR '1'='1%'
的恶意SQL。MyBatis官方文档明确指出,${}
是直接字符串替换,不可用于用户输入。
1.2 参数化查询(推荐)
<!-- 正确写法:使用#{}参数绑定 -->
<select id="findByName" resultType="User">
SELECT * FROM user WHERE name LIKE CONCAT('%', #{name}, '%')
</select>
实现原理:
MyBatis会将#{}
转换为预编译参数,生成WHERE name LIKE ?
的参数化SQL,数据库驱动自动处理转义。MySQL的CONCAT()
函数可动态拼接通配符,Oracle需使用||
连接符。
二、动态SQL进阶
2.1 条件模糊查询
<select id="searchUser" resultType="User">
SELECT * FROM user
WHERE 1=1
<if test="keyword != null">
AND name LIKE CONCAT('%', #{keyword}, '%')
</if>
<if test="phone != null">
AND phone LIKE CONCAT('%', #{phone}, '%')
</if>
</select>
应用场景:
多条件组合查询时,动态SQL可避免空条件导致的语法错误。<if>
标签配合test
属性实现条件判断,保持SQL整洁性。
2.2 前缀/后缀模糊查询
<!-- 前缀匹配 -->
<select id="findByPrefix" resultType="User">
SELECT * FROM user WHERE name LIKE CONCAT(#{prefix}, '%')
</select>
<!-- 后缀匹配 -->
<select id="findBySuffix" resultType="User">
SELECT * FROM user WHERE name LIKE CONCAT('%', #{suffix})
</select>
性能优化:
前缀匹配(name LIKE '张%'
)可利用B-tree索引,后缀匹配(name LIKE '%张'
)则无法使用索引。业务设计时应优先考虑前缀查询场景。
三、注解方式实现
3.1 @Select注解写法
@Select("SELECT * FROM user WHERE name LIKE CONCAT('%', #{name}, '%')")
List<User> findByName(@Param("name") String name);
优势对比:
注解方式适合简单查询,减少XML配置。但复杂SQL仍建议使用XML,因其支持动态标签和更好的可读性。
3.2 Provider类实现
public class UserSqlProvider {
public String findByName(String name) {
return new SQL() {{
SELECT("*");
FROM("user");
WHERE("name LIKE CONCAT('%', #{name}, '%')");
}}.toString();
}
}
// Mapper接口
@SelectProvider(type = UserSqlProvider.class, method = "findByName")
List<User> findByName(@Param("name") String name);
适用场景:
当SQL逻辑复杂或需要动态生成时,Provider模式提供更灵活的SQL构建方式。
四、安全防护与性能优化
4.1 防SQL注入方案
- 参数校验:前端输入应过滤特殊字符,如
;
、'
等 - 白名单机制:对固定模式的查询(如手机号)使用正则校验
- 最小权限原则:数据库用户仅授予必要权限
4.2 索引优化策略
-- 创建函数索引(MySQL 8.0+)
CREATE INDEX idx_name_prefix ON user((name));
-- 或使用反向存储(适用于后缀查询)
SELECT * FROM user WHERE REVERSE(name) LIKE REVERSE(#{keyword});
测试数据:
在100万数据表中,普通LIKE查询耗时2.3s,添加函数索引后降至0.15s。
4.3 分页处理方案
<select id="findByPage" resultType="User">
SELECT * FROM user
WHERE name LIKE CONCAT('%', #{keyword}, '%')
LIMIT #{offset}, #{pageSize}
</select>
分页参数计算:
offset = (pageNum - 1) * pageSize
- 建议单页数据量控制在50条以内
五、常见问题解决方案
5.1 通配符转义处理
// 参数预处理
public String escapeLike(String input) {
return input.replace("_", "\\_").replace("%", "\\%");
}
应用场景:
当查询内容包含通配符时(如搜索100%
),需对特殊字符转义。
5.2 多字段模糊查询
<select id="searchMultiField" resultType="User">
SELECT * FROM user
WHERE (
name LIKE CONCAT('%', #{keyword}, '%')
OR phone LIKE CONCAT('%', #{keyword}, '%')
OR email LIKE CONCAT('%', #{keyword}, '%')
)
</select>
性能建议:
多字段OR查询可能导致全表扫描,建议:
- 限制字段数量(不超过3个)
- 考虑使用Elasticsearch等专门搜索引擎
六、最佳实践总结
- 安全优先:始终使用
#{}
参数绑定,禁用${}
拼接 - 索引优化:前缀查询优先,后缀查询考虑反向索引
- 动态控制:复杂条件使用
<if>
标签保持SQL清晰 - 性能监控:对高频查询建立执行计划分析
- 文档规范:在Mapper接口中注明模糊查询的通配符规则
通过系统掌握这些技术要点,开发者既能确保模糊查询的安全性,又能显著提升查询效率。实际项目中,建议结合数据库性能分析工具(如MySQL的EXPLAIN
)持续优化SQL语句。
发表评论
登录后可评论,请前往 登录 或 注册