MyBatis模糊查询:LIKE语句的正确使用与最佳实践
2025.09.19 15:54浏览量:0简介:本文详细解析MyBatis中LIKE模糊查询的四种实现方式,结合XML映射与注解开发两种场景,提供防SQL注入方案及性能优化建议。
MyBatis模糊查询:LIKE语句的正确使用与最佳实践
在MyBatis框架中进行数据库模糊查询时,LIKE语句的正确使用直接关系到查询结果的准确性和系统安全性。本文将从基础语法、参数处理、安全防护和性能优化四个维度,系统讲解MyBatis中LIKE查询的最佳实践。
一、基础语法实现方式
1.1 XML映射文件实现
在XML映射文件中,LIKE查询主要有三种写法:
方式一:直接拼接(不推荐)
<select id="findByName" resultType="User">
SELECT * FROM user WHERE name LIKE '%${name}%'
</select>
这种方式存在SQL注入风险,当传入的name
参数包含恶意SQL片段时,会导致数据库安全问题。
方式二:参数化查询(推荐)
<select id="findByName" resultType="User">
SELECT * FROM user WHERE name LIKE CONCAT('%', #{name}, '%')
</select>
或使用数据库特定的连接函数:
<!-- MySQL -->
<select id="findByName" resultType="User">
SELECT * FROM user WHERE name LIKE '%' || #{name} || '%'
</select>
<!-- Oracle -->
<select id="findByName" resultType="User">
SELECT * FROM user WHERE name LIKE '%' || #{name} || '%'
</select>
方式三:动态SQL拼接
<select id="findByName" resultType="User">
SELECT * FROM user
<where>
<if test="name != null">
name LIKE CONCAT('%', #{name}, '%')
</if>
</where>
</select>
1.2 注解方式实现
使用@Select
注解实现模糊查询:
@Select("SELECT * FROM user WHERE name LIKE CONCAT('%', #{name}, '%')")
List<User> findByName(@Param("name") String name);
二、参数处理技巧
2.1 前后模糊查询
实现”包含”查询(name字段包含参数值):
<select id="findByName" resultType="User">
SELECT * FROM user WHERE name LIKE CONCAT('%', #{name}, '%')
</select>
2.2 前缀模糊查询
实现”以…开头”查询:
<select id="findByPrefix" resultType="User">
SELECT * FROM user WHERE name LIKE CONCAT(#{name}, '%')
</select>
2.3 后缀模糊查询
实现”以…结尾”查询:
<select id="findBySuffix" resultType="User">
SELECT * FROM user WHERE name LIKE CONCAT('%', #{name})
</select>
2.4 多字段模糊查询
<select id="findByMultiCondition" resultType="User">
SELECT * FROM user
WHERE name LIKE CONCAT('%', #{name}, '%')
OR phone LIKE CONCAT('%', #{phone}, '%')
</select>
三、安全防护措施
3.1 防止SQL注入
必须使用#{}
参数占位符,避免使用${}
直接拼接:
<!-- 安全写法 -->
<select id="safeSearch" resultType="User">
SELECT * FROM user WHERE name LIKE CONCAT('%', #{keyword}, '%')
</select>
<!-- 危险写法 -->
<select id="unsafeSearch" resultType="User">
SELECT * FROM user WHERE name LIKE '%${keyword}%'
</select>
3.2 参数校验
在Service层进行参数校验:
public List<User> searchUsers(String keyword) {
if (keyword == null || keyword.trim().isEmpty()) {
throw new IllegalArgumentException("搜索关键词不能为空");
}
// 去除特殊字符
String safeKeyword = keyword.replaceAll("[';\\-]", "");
return userMapper.findByName(safeKeyword);
}
3.3 最小权限原则
数据库用户应只拥有必要的查询权限,避免使用具有DDL权限的高权限账户。
四、性能优化建议
4.1 索引优化
对LIKE查询字段建立合适的索引:
-- 创建函数索引(MySQL 8.0+)
CREATE INDEX idx_user_name ON user((name));
-- 或使用反向索引(适用于后缀查询)
CREATE INDEX idx_user_name_reverse ON user(REVERSE(name));
4.2 查询条件优化
避免在索引列上使用前导通配符:
<!-- 不推荐:无法使用索引 -->
<select id="findByNameStart" resultType="User">
SELECT * FROM user WHERE name LIKE '%张'
</select>
<!-- 推荐:可以使用索引 -->
<select id="findByNameEnd" resultType="User">
SELECT * FROM user WHERE name LIKE '张%'
</select>
4.3 分页处理
大数据量时必须实现分页:
<select id="findByNamePage" resultType="User">
SELECT * FROM user
WHERE name LIKE CONCAT('%', #{name}, '%')
LIMIT #{offset}, #{pageSize}
</select>
4.4 缓存策略
对频繁执行的模糊查询考虑使用二级缓存:
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
五、常见问题解决方案
5.1 特殊字符处理
当搜索词包含%
或_
时:
<select id="findBySpecialChar" resultType="User">
SELECT * FROM user
WHERE name LIKE CONCAT('%', REPLACE(REPLACE(#{name}, '\\', '\\\\'), '%', '\\%'), '%') ESCAPE '\\'
</select>
5.2 空值处理
<select id="findByNameOptional" resultType="User">
SELECT * FROM user
<where>
<if test="name != null and name != ''">
name LIKE CONCAT('%', #{name}, '%')
</if>
</where>
</select>
5.3 多数据库兼容
使用MyBatis的动态SQL处理不同数据库的语法差异:
<select id="findByName" resultType="User">
SELECT * FROM user WHERE name LIKE
<choose>
<when test="_databaseId == 'mysql'">
CONCAT('%', #{name}, '%')
</when>
<when test="_databaseId == 'oracle'">
'%' || #{name} || '%'
</when>
<otherwise>
'%' + #{name} + '%'
</otherwise>
</choose>
</select>
六、最佳实践总结
- 始终使用参数化查询:坚持使用
#{}
占位符,杜绝SQL注入风险 - 合理设计索引:根据查询模式设计适当的索引
- 实现分页机制:避免大数据量查询导致性能问题
- 进行参数校验:在Service层验证输入参数
- 考虑数据库兼容:处理不同数据库的语法差异
- 优化查询条件:避免在索引列上使用前导通配符
通过遵循这些最佳实践,开发者可以在MyBatis中安全、高效地实现模糊查询功能,既保证系统安全性,又提升查询性能。在实际开发中,建议结合具体业务场景选择最适合的实现方式,并通过性能测试验证优化效果。
发表评论
登录后可评论,请前往 登录 或 注册