MyBatis-Plus作为MyBatis的增强工具,提供了丰富的模糊查询方法,其中like、likeLeft、likeRight是最常用的三种模糊查询方式。本文将详细介绍这三种方法的区别、使用场景及最佳实践。
一、三种like方法的核心区别
| 方法名称 | SQL等价形式 | 匹配方式 | 适用场景 |
|---|---|---|---|
like | LIKE '%keyword%' | 全模糊匹配 | 查询包含指定关键字的记录 |
likeLeft | LIKE '%keyword' | 左模糊匹配 | 查询以指定关键字结尾的记录 |
likeRight | LIKE 'keyword%' | 右模糊匹配 | 查询以指定关键字开头的记录 |
二、基础用法示例
1. QueryWrapper方式
// 全模糊查询:查询名字包含"张"的用户
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", "张");
List<User> users = userMapper.selectList(queryWrapper);
// 左模糊查询:查询邮箱以"com"结尾的用户
queryWrapper.likeLeft("email", "com");
// 右模糊查询:查询手机号以"138"开头的用户
queryWrapper.likeRight("phone", "138");
2. LambdaQueryWrapper方式(推荐)
// 全模糊查询
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.like(User::getName, "张");
// 左模糊查询
lambdaWrapper.likeLeft(User::getEmail, "com");
// 右模糊查询
lambdaWrapper.likeRight(User::getPhone, "138");
三、条件性查询
在实际开发中,我们经常需要根据参数是否为空来动态添加查询条件:
public List<User> searchUsers(String name, String email) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
// 只有name不为空时才添加模糊查询条件
wrapper.like(StringUtils.isNotBlank(name), User::getName, name);
// 只有email不为空时才添加模糊查询条件
wrapper.like(StringUtils.isNotBlank(email), User::getEmail, email);
return userMapper.selectList(wrapper);
}
四、多字段模糊查询
1. OR连接多个字段
// 查询名字或邮箱包含"张"的用户
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(User::getName, "张")
.or()
.like(User::getEmail, "张");
2. AND-OR复杂组合
// 查询状态为启用,且名字或邮箱包含"张"的用户
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getStatus, 1)
.and(w -> w.like(User::getName, "张")
.or()
.like(User::getEmail, "张"));
五、性能优化建议
1. 避免前导通配符
likeLeft(%keyword)会导致索引失效,在数据量大的表中应谨慎使用。如果必须使用,可以考虑:
- 使用全文索引(FULLTEXT)
- 使用搜索引擎(Elasticsearch)
- 优化数据库表结构
2. 只查询必要字段
// 只查询id和name字段,避免SELECT *
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.select(User::getId, User::getName)
.like(User::getName, "张");
3. 分页查询
// 分页查询
Page<User> page = new Page<>(1, 10);
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(User::getName, "张");
Page<User> result = userMapper.selectPage(page, wrapper);
六、常见问题与解决方案
1. 数据库兼容性问题
不同数据库对CONCAT函数的支持不同:
// Oracle数据库需要特殊处理
wrapper.apply("name LIKE '%' || {0} || '%'", keyword);
2. 空字符串处理
// 避免空字符串导致查询条件失效
if (StringUtils.isNotBlank(keyword)) {
wrapper.like(User::getName, keyword);
}
3. SQL注入防护
MyBatis-Plus默认使用预编译语句,无需担心SQL注入问题。但手动拼接SQL时需注意:
// 安全的方式
wrapper.apply("name LIKE CONCAT('%', #{keyword}, '%')");
// 危险的方式(不推荐)
wrapper.apply("name LIKE '%" + keyword + "%'");
七、实际应用场景
场景1:用户管理搜索
public Page<User> searchUsers(UserSearchVO searchVO) {
Page<User> page = new Page<>(searchVO.getPageNum(), searchVO.getPageSize());
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
// 姓名模糊查询
wrapper.like(StringUtils.isNotBlank(searchVO.getName()),
User::getName, searchVO.getName());
// 手机号右模糊查询(前缀匹配)
wrapper.likeRight(StringUtils.isNotBlank(searchVO.getPhone()),
User::getPhone, searchVO.getPhone());
// 邮箱左模糊查询(后缀匹配)
wrapper.likeLeft(StringUtils.isNotBlank(searchVO.getEmail()),
User::getEmail, searchVO.getEmail());
return userMapper.selectPage(page, wrapper);
}
场景2:商品搜索
public List<Product> searchProducts(String keyword) {
LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<>();
// 多字段OR查询
wrapper.like(Product::getProductName, keyword)
.or()
.like(Product::getProductDesc, keyword)
.or()
.like(Product::getCategoryName, keyword);
return productMapper.selectList(wrapper);
}
总结
MyBatis-Plus的like系列方法为模糊查询提供了强大的支持:
like:全模糊匹配,适用于包含性搜索likeLeft:左模糊匹配,适用于后缀匹配likeRight:右模糊匹配,适用于前缀匹配(性能最佳)
在实际开发中,建议:
- 优先使用
LambdaQueryWrapper,避免字段名硬编码 - 合理选择模糊查询方式,避免性能问题
- 结合分页和字段选择优化查询性能
- 注意数据库兼容性和SQL注入防护
通过合理使用这些方法,可以显著提升开发效率和代码可维护性。