SpringBoot+Mybatis+Mysql模糊查询实战指南
2025.09.19 15:54浏览量:2简介:本文详细讲解SpringBoot结合Mybatis实现Mysql模糊查询的完整方案,包含技术原理、代码实现及性能优化建议,助力开发者高效构建搜索功能。
SpringBoot+Mybatis+Mysql模糊查询实战指南
一、技术架构与核心原理
在Java企业级开发中,SpringBoot+Mybatis+Mysql的组合已成为数据持久层的黄金搭档。模糊查询作为高频需求,其核心是通过SQL的LIKE操作符实现字符串模式匹配。Mybatis通过动态SQL和注解方式,将Java方法调用转换为高效的数据库查询语句,而SpringBoot则简化了整个框架的集成过程。
1.1 模糊查询的SQL基础
Mysql支持两种模糊匹配符号:
%:匹配任意长度字符(包括零个字符)_:匹配单个字符
示例:
SELECT * FROM users WHERE name LIKE '%张%'; -- 包含"张"的所有记录SELECT * FROM products WHERE code LIKE 'A_B%'; -- 第二个字符为"B",首字符为"A"的记录
1.2 Mybatis的两种实现方式
- XML映射文件:通过
<select>标签和${}、#{}参数占位符 - 注解方式:使用
@Select注解直接编写SQL
二、完整实现步骤
2.1 环境准备
- 创建SpringBoot项目(2.7.x版本)
- 添加依赖:
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency>
2.2 实体类设计
@Datapublic class User {private Long id;private String username;private String email;// 其他字段...}
2.3 Mapper接口实现
方案一:XML映射文件
创建
UserMapper.xml:<mapper namespace="com.example.mapper.UserMapper"><select id="searchByKeyword" resultType="com.example.entity.User">SELECT * FROM userWHERE username LIKE CONCAT('%', #{keyword}, '%')OR email LIKE CONCAT('%', #{keyword}, '%')</select></mapper>
对应Mapper接口:
public interface UserMapper {List<User> searchByKeyword(@Param("keyword") String keyword);}
方案二:注解方式
@Mapperpublic interface UserMapper {@Select({"<script>","SELECT * FROM user","WHERE username LIKE CONCAT('%', #{keyword}, '%')","<if test='emailSearch != null'>","OR email LIKE CONCAT('%', #{keyword}, '%')","</if>","</script>"})List<User> searchByKeyword(@Param("keyword") String keyword,@Param("emailSearch") Boolean emailSearch);}
2.4 Service层实现
@Servicepublic class UserService {@Autowiredprivate UserMapper userMapper;public List<User> searchUsers(String keyword) {if (StringUtils.isEmpty(keyword)) {return Collections.emptyList();}return userMapper.searchByKeyword(keyword);}// 带条件的高级搜索public List<User> advancedSearch(String keyword, boolean searchEmail) {return userMapper.searchByKeyword(keyword, searchEmail);}}
2.5 Controller层实现
@RestController@RequestMapping("/api/users")public class UserController {@Autowiredprivate UserService userService;@GetMapping("/search")public ResponseEntity<List<User>> search(@RequestParam String keyword,@RequestParam(required = false, defaultValue = "false") boolean searchEmail) {List<User> users = userService.advancedSearch(keyword, searchEmail);return ResponseEntity.ok(users);}}
三、性能优化策略
3.1 索引优化
对搜索字段建立索引:
ALTER TABLE user ADD INDEX idx_username (username);ALTER TABLE user ADD INDEX idx_email (email);
全文索引方案(Mysql 5.6+):
ALTER TABLE user ADD FULLTEXT INDEX ft_idx (username, email);-- 使用MATCH AGAINST替代LIKESELECT * FROM user WHERE MATCH(username, email) AGAINST('张三' IN NATURAL LANGUAGE MODE);
3.2 分页处理
// Mapper接口@Select("SELECT * FROM user WHERE username LIKE CONCAT('%', #{keyword}, '%') LIMIT #{offset}, #{size}")List<User> searchWithPagination(@Param("keyword") String keyword,@Param("offset") int offset,@Param("size") int size);// Service层public PageResult<User> searchWithPage(String keyword, int page, int size) {int offset = (page - 1) * size;List<User> data = userMapper.searchWithPagination(keyword, offset, size);long total = userMapper.countByKeyword(keyword); // 需额外实现计数方法return new PageResult<>(data, total, page, size);}
3.3 防SQL注入
- 永远使用
#{}而非${}(除非必要场景) - 对输入参数进行校验:
public List<User> safeSearch(String keyword) {if (keyword == null || keyword.length() > 50) { // 限制长度throw new IllegalArgumentException("Invalid keyword");}// 转义特殊字符(可选)String safeKeyword = keyword.replaceAll("([%_])", "\\\\$1");return userMapper.searchByKeyword(safeKeyword);}
四、高级应用场景
4.1 多字段组合搜索
// Mapper接口@Select({"<script>","SELECT * FROM user","<where>","<if test='username != null'>","username LIKE CONCAT('%', #{username}, '%')","</if>","<if test='email != null'>","AND email LIKE CONCAT('%', #{email}, '%')","</if>","<if test='phone != null'>","AND phone LIKE CONCAT('%', #{phone}, '%')","</if>","</where>","</script>"})List<User> multiFieldSearch(@Param("username") String username,@Param("email") String email,@Param("phone") String phone);
4.2 拼音模糊搜索(需额外处理)
添加拼音字段:
ALTER TABLE user ADD COLUMN username_pinyin VARCHAR(100);-- 通过触发器或应用层维护拼音字段
修改搜索SQL:
SELECT * FROM userWHERE username LIKE CONCAT('%', #{keyword}, '%')OR username_pinyin LIKE CONCAT('%', #{pinyinKeyword}, '%')
五、常见问题解决方案
5.1 中文乱码问题
确保数据库连接字符串包含字符集设置:
spring.datasource.url=jdbc
//localhost:3306/db?useUnicode=true&characterEncoding=utf8
检查表字段字符集:
SHOW CREATE TABLE user; -- 应显示CHARSET=utf8mb4
5.2 性能瓶颈排查
使用EXPLAIN分析查询:
EXPLAIN SELECT * FROM user WHERE username LIKE '%张%';
监控慢查询日志:
# application.propertiesspring.datasource.hikari.data-source-properties.slowQueryThresholdMillis=2000
六、最佳实践总结
- 索引策略:对高频搜索字段建立单独索引,全文索引适用于长文本搜索
- 分页处理:必须实现分页,避免返回大量数据
- 安全防护:严格校验输入参数,防止SQL注入
- 性能监控:建立慢查询监控机制
- 扩展性设计:考虑使用Elasticsearch等专用搜索引擎处理复杂搜索需求
通过以上方案,开发者可以构建出高效、安全、可扩展的模糊查询功能。实际项目中,建议根据数据量和性能要求,在纯SQL模糊查询与专用搜索引擎之间做出合理选择。对于千万级数据量,建议采用Elasticsearch+Mysql的组合方案,既保证搜索灵活性,又维持事务一致性。

发表评论
登录后可评论,请前往 登录 或 注册