logo

SpringBoot+Mybatis+Mysql模糊查询实战指南

作者:KAKAKA2025.09.19 15:54浏览量:0

简介:本文详细讲解SpringBoot结合Mybatis实现Mysql模糊查询的完整方案,包含技术原理、代码实现及性能优化建议,助力开发者高效构建搜索功能。

SpringBoot+Mybatis+Mysql模糊查询实战指南

一、技术架构与核心原理

在Java企业级开发中,SpringBoot+Mybatis+Mysql的组合已成为数据持久层的黄金搭档。模糊查询作为高频需求,其核心是通过SQL的LIKE操作符实现字符串模式匹配。Mybatis通过动态SQL和注解方式,将Java方法调用转换为高效的数据库查询语句,而SpringBoot则简化了整个框架的集成过程。

1.1 模糊查询的SQL基础

Mysql支持两种模糊匹配符号:

  • %:匹配任意长度字符(包括零个字符)
  • _:匹配单个字符

示例:

  1. SELECT * FROM users WHERE name LIKE '%张%'; -- 包含"张"的所有记录
  2. SELECT * FROM products WHERE code LIKE 'A_B%'; -- 第二个字符为"B",首字符为"A"的记录

1.2 Mybatis的两种实现方式

  1. XML映射文件:通过<select>标签和${}#{}参数占位符
  2. 注解方式:使用@Select注解直接编写SQL

二、完整实现步骤

2.1 环境准备

  1. 创建SpringBoot项目(2.7.x版本)
  2. 添加依赖:
    1. <dependency>
    2. <groupId>org.mybatis.spring.boot</groupId>
    3. <artifactId>mybatis-spring-boot-starter</artifactId>
    4. <version>2.2.2</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>mysql</groupId>
    8. <artifactId>mysql-connector-java</artifactId>
    9. <scope>runtime</scope>
    10. </dependency>

2.2 实体类设计

  1. @Data
  2. public class User {
  3. private Long id;
  4. private String username;
  5. private String email;
  6. // 其他字段...
  7. }

2.3 Mapper接口实现

方案一:XML映射文件

  1. 创建UserMapper.xml

    1. <mapper namespace="com.example.mapper.UserMapper">
    2. <select id="searchByKeyword" resultType="com.example.entity.User">
    3. SELECT * FROM user
    4. WHERE username LIKE CONCAT('%', #{keyword}, '%')
    5. OR email LIKE CONCAT('%', #{keyword}, '%')
    6. </select>
    7. </mapper>
  2. 对应Mapper接口:

    1. public interface UserMapper {
    2. List<User> searchByKeyword(@Param("keyword") String keyword);
    3. }

方案二:注解方式

  1. @Mapper
  2. public interface UserMapper {
  3. @Select({
  4. "<script>",
  5. "SELECT * FROM user",
  6. "WHERE username LIKE CONCAT('%', #{keyword}, '%')",
  7. "<if test='emailSearch != null'>",
  8. "OR email LIKE CONCAT('%', #{keyword}, '%')",
  9. "</if>",
  10. "</script>"
  11. })
  12. List<User> searchByKeyword(
  13. @Param("keyword") String keyword,
  14. @Param("emailSearch") Boolean emailSearch
  15. );
  16. }

2.4 Service层实现

  1. @Service
  2. public class UserService {
  3. @Autowired
  4. private UserMapper userMapper;
  5. public List<User> searchUsers(String keyword) {
  6. if (StringUtils.isEmpty(keyword)) {
  7. return Collections.emptyList();
  8. }
  9. return userMapper.searchByKeyword(keyword);
  10. }
  11. // 带条件的高级搜索
  12. public List<User> advancedSearch(String keyword, boolean searchEmail) {
  13. return userMapper.searchByKeyword(keyword, searchEmail);
  14. }
  15. }

2.5 Controller层实现

  1. @RestController
  2. @RequestMapping("/api/users")
  3. public class UserController {
  4. @Autowired
  5. private UserService userService;
  6. @GetMapping("/search")
  7. public ResponseEntity<List<User>> search(
  8. @RequestParam String keyword,
  9. @RequestParam(required = false, defaultValue = "false") boolean searchEmail) {
  10. List<User> users = userService.advancedSearch(keyword, searchEmail);
  11. return ResponseEntity.ok(users);
  12. }
  13. }

三、性能优化策略

3.1 索引优化

  1. 对搜索字段建立索引:

    1. ALTER TABLE user ADD INDEX idx_username (username);
    2. ALTER TABLE user ADD INDEX idx_email (email);
  2. 全文索引方案(Mysql 5.6+):

    1. ALTER TABLE user ADD FULLTEXT INDEX ft_idx (username, email);
    2. -- 使用MATCH AGAINST替代LIKE
    3. SELECT * FROM user WHERE MATCH(username, email) AGAINST('张三' IN NATURAL LANGUAGE MODE);

3.2 分页处理

  1. // Mapper接口
  2. @Select("SELECT * FROM user WHERE username LIKE CONCAT('%', #{keyword}, '%') LIMIT #{offset}, #{size}")
  3. List<User> searchWithPagination(
  4. @Param("keyword") String keyword,
  5. @Param("offset") int offset,
  6. @Param("size") int size
  7. );
  8. // Service层
  9. public PageResult<User> searchWithPage(String keyword, int page, int size) {
  10. int offset = (page - 1) * size;
  11. List<User> data = userMapper.searchWithPagination(keyword, offset, size);
  12. long total = userMapper.countByKeyword(keyword); // 需额外实现计数方法
  13. return new PageResult<>(data, total, page, size);
  14. }

3.3 防SQL注入

  1. 永远使用#{}而非${}(除非必要场景)
  2. 对输入参数进行校验:
    1. public List<User> safeSearch(String keyword) {
    2. if (keyword == null || keyword.length() > 50) { // 限制长度
    3. throw new IllegalArgumentException("Invalid keyword");
    4. }
    5. // 转义特殊字符(可选)
    6. String safeKeyword = keyword.replaceAll("([%_])", "\\\\$1");
    7. return userMapper.searchByKeyword(safeKeyword);
    8. }

四、高级应用场景

4.1 多字段组合搜索

  1. // Mapper接口
  2. @Select({
  3. "<script>",
  4. "SELECT * FROM user",
  5. "<where>",
  6. "<if test='username != null'>",
  7. "username LIKE CONCAT('%', #{username}, '%')",
  8. "</if>",
  9. "<if test='email != null'>",
  10. "AND email LIKE CONCAT('%', #{email}, '%')",
  11. "</if>",
  12. "<if test='phone != null'>",
  13. "AND phone LIKE CONCAT('%', #{phone}, '%')",
  14. "</if>",
  15. "</where>",
  16. "</script>"
  17. })
  18. List<User> multiFieldSearch(
  19. @Param("username") String username,
  20. @Param("email") String email,
  21. @Param("phone") String phone
  22. );

4.2 拼音模糊搜索(需额外处理)

  1. 添加拼音字段:

    1. ALTER TABLE user ADD COLUMN username_pinyin VARCHAR(100);
    2. -- 通过触发器或应用层维护拼音字段
  2. 修改搜索SQL:

    1. SELECT * FROM user
    2. WHERE username LIKE CONCAT('%', #{keyword}, '%')
    3. OR username_pinyin LIKE CONCAT('%', #{pinyinKeyword}, '%')

五、常见问题解决方案

5.1 中文乱码问题

  1. 确保数据库连接字符串包含字符集设置:

    1. spring.datasource.url=jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8
  2. 检查表字段字符集:

    1. SHOW CREATE TABLE user; -- 应显示CHARSET=utf8mb4

5.2 性能瓶颈排查

  1. 使用EXPLAIN分析查询:

    1. EXPLAIN SELECT * FROM user WHERE username LIKE '%张%';
  2. 监控慢查询日志

    1. # application.properties
    2. spring.datasource.hikari.data-source-properties.slowQueryThresholdMillis=2000

六、最佳实践总结

  1. 索引策略:对高频搜索字段建立单独索引,全文索引适用于长文本搜索
  2. 分页处理:必须实现分页,避免返回大量数据
  3. 安全防护:严格校验输入参数,防止SQL注入
  4. 性能监控:建立慢查询监控机制
  5. 扩展性设计:考虑使用Elasticsearch等专用搜索引擎处理复杂搜索需求

通过以上方案,开发者可以构建出高效、安全、可扩展的模糊查询功能。实际项目中,建议根据数据量和性能要求,在纯SQL模糊查询与专用搜索引擎之间做出合理选择。对于千万级数据量,建议采用Elasticsearch+Mysql的组合方案,既保证搜索灵活性,又维持事务一致性。

相关文章推荐

发表评论