Mybatis-Plus 实现查询条件为空时不生效

当我们查询条件中的值不确定是否有空值时,我们期待查询时,Mybatis+能自动帮我们判空。

比如这样:

this.page(
      new Query<OperatorsEntity>().getPage(queryFields),
      new QueryWrapper<OperatorsEntity>()
      .eq("province_id",queryFields.getProvinceId())
      .eq("city_id",queryFields.getCityId())
      .eq("area_id",queryFields.getAreaId())
      .like("name",queryFields.getNameLike())
);

我们期待的结果是:“province_id”、“city_id”、“area_id”、"name"等几个字段中,如果有空的(比如查询表单中没有填这个查询条件),就不查询。
然而事实上,如果这样去写,结果会是:Mybatis+把所有条件都构造出来,为空的就按null查询,like则是查询: %null%

解决方案:

  • 提供一个有条件排空功能的ExcludeEmptyQueryWrapper(后附代码),有类似需求的用该queryWrapper来构建条件,一劳永逸解决问题,使用:
this.page(
      new Query<OperatorsEntity>().getPage(queryFields),
      new ExcludeEmptyQueryWrapper<OperatorsEntity>()
      .eq("province_id",queryFields.getProvinceId())
      .eq("city_id",queryFields.getCityId())
      .eq("area_id",queryFields.getAreaId())
      .like("name",queryFields.getNameLike())
);
  • ExcludeEmptyQueryWrapper 代码如下:
/**
 * 继承QueryWrapper,重写其构造条件方法,使条件为null的查询条件,不再执行。
 * @since Mybatis+ version: 3.x.x
 * @author firewolf
 */
public class ExcludeEmptyQueryWrapper<T> extends QueryWrapper<T> {
    @Override
    public QueryWrapper<T> eq(boolean condition, String column, Object val) {
        condition = !Objects.isNull(val);
        return super.eq(condition, column, val);
    }

    @Override
    public QueryWrapper<T> ne(boolean condition, String column, Object val) {
        condition = !Objects.isNull(val);
        return super.ne(condition, column, val);
    }

    @Override
    public QueryWrapper<T> gt(boolean condition, String column, Object val) {
        condition = !Objects.isNull(val);
        return super.gt(condition, column, val);
    }

    @Override
    public QueryWrapper<T> ge(boolean condition, String column, Object val) {
        condition = !Objects.isNull(val);
        return super.ge(condition, column, val);
    }

    @Override
    public QueryWrapper<T> lt(boolean condition, String column, Object val) {
        condition = !Objects.isNull(val);
        return super.lt(condition, column, val);
    }

    @Override
    public QueryWrapper<T> le(boolean condition, String column, Object val) {
        condition = !Objects.isNull(val);
        return super.le(condition, column, val);
    }

    @Override
    public QueryWrapper<T> like(boolean condition, String column, Object val) {
        condition = !Objects.isNull(val);
        return super.like(condition, column, val);
    }

    @Override
    public QueryWrapper<T> notLike(boolean condition, String column, Object val) {
        condition = !Objects.isNull(val);
        return super.notLike(condition, column, val);
    }

    @Override
    public QueryWrapper<T> likeLeft(boolean condition, String column, Object val) {
        condition = !Objects.isNull(val);
        return super.likeLeft(condition, column, val);
    }

    @Override
    public QueryWrapper<T> likeRight(boolean condition, String column, Object val) {
        condition = !Objects.isNull(val);
        return super.likeRight(condition, column, val);
    }

    @Override
    public QueryWrapper<T> between(boolean condition, String column, Object val1, Object val2) {
        if(Objects.isNull(val1) && Objects.isNull(val2)){
            condition = false;
        }else if(Objects.isNull(val1)){
            return super.lt(true,column,val2);
        }else if(Objects.isNull(val2)){
            return super.ge(true,column,val1);
        }
        return super.between(condition, column, val1, val2);
    }

    @Override
    public QueryWrapper<T> notBetween(boolean condition, String column, Object val1, Object val2) {
        if(Objects.isNull(val1) && Objects.isNull(val2)){
            condition = false;
        }else if(Objects.isNull(val1)){
            return super.lt(true,column,val2);
        }else if(Objects.isNull(val2)){
            return super.ge(true,column,val1);
        }
        return super.notBetween(condition, column, val1, val2);
    }
}
<think>首先,用户的问题是:“我想查找MyBatis-plus进行模糊查询的方法 请问MyBatis-plus实现模糊查询的方法”。用户想了解如何使用MyBatis-Plus实现模糊查询。 现在,回顾系统级指令: - 所有行内数学表达式用 `$...$` 格式。 - 独立公式用 `$$...$$` 格式。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如 `[^1]`。 用户提供了五个引用: - 引用[1]: 关于防止模糊查询中 `%` 导致全表扫描的问题。 - 引用[2]: 使用SpringBoot和Mybatis-plus实现分页查询,包括模糊查询- 引用[3]: Mybatis-plus-join插件用于多表连接查询- 引用[4]: MyBatis-Plus条件构造器用法。 - 引用[5]: 配置MybatisPlusInterceptor用于分页和模糊查询。 用户的问题具体是查找MyBatis-plus实现模糊查询的方法,所以我需要聚焦在模糊查询上。引用[1]提到了模糊查询中的通配符问题,引用[2]提到了模糊查询实现,引用[5]涉及配置。 关键点是模糊查询实现方法。在MyBatis-Plus中,模糊查询通常使用条件构造器(如QueryWrapper或LambdaQueryWrapper)中的 `like` 方法来实现。 从引用[2]: “这部分代码是通过mybatis-plus中的Lambada来构造查询条件,作用就是人员姓名模糊查询、状态查询、手机号查询” —— 这表明使用LambdaQueryWrapper可以实现模糊查询。 从引用[4]: “MyBatis-Plus条件构造器用法”,提到了条件构造器用于查询。 引用[1]提醒了在模糊查询中处理 `%` 的必要性,以避免安全风险。 引用[5]展示了配置MybatisPlusInterceptor,但主要是用于分页,而是直接模糊查询过,它可以结合使用。 所以,回答应该包括: 1. **基本方法**:使用QueryWrapper或LambdaQueryWrapper的 `like` 方法。 2. **示例代码**:展示如何使用。 3. **注意事项**:来自引用[1],处理通配符以避免全表扫描。 4. **引用标识**:在解释自然地添加引用标识。 结构回答: - 简要介绍。 - 详细解释方法。 - 提供代码示例。 - 提到安全和优化。 - 生成相关问题。 代码示例:基于引用[2],使用LambdaQueryWrapper实现模糊查询。 示例代码: ```java LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.like(User::getName, "John"); // 模糊查询name字段包含"John"的记录 List<User> userList = userMapper.selectList(wrapper); ``` 或者使用QueryWrapper: ```java QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.like("name", "John"); List<User> userList = userMapper.selectList(wrapper); ``` 处理通配符:为了防止用户输入 `%` 或 `_` 导致问题,可以在应用层转义这些字符,或者在查询处理。引用[1]建议实现通配符转义拦截器。 在回答中,自然地添加引用: - 当解释Like方法,引用[4]。 - 当提到Lambda构造,引用[2]。 - 当警告通配符风险,引用[1]。 生成相关问题:在最后添加。 回答语言:中文。 最终回答结构: 1. 介绍模糊查询MyBatis-Plus中的重要性。 2. 详细讲解实现方法: - 使用QueryWrapper或LambdaQueryWrapper。 - 使用 `like` 方法。 - 示例代码。 3. 注意事项:转义通配符以避免风险(基于引用[1])。 4. 生成相关问题。 </think>以下是基于MyBatis-Plus实现模糊查询的详细方法。我将结合实际需求逐步解释核心步骤、代码示例和注意事项,确保回答清晰可靠。关键是通过MyBatis-Plus条件构造器(如 `QueryWrapper` 或 `LambdaQueryWrapper`)的 `like` 方法实现模糊查询,同需防范通配符风险。 ### 一、模糊查询的基本实现方法 在MyBatis-Plus中,模糊查询主要通过条件构造器的 `like` 方法实现。该方法会自动生成类似 `LIKE '%value%'` 的SQL语句,匹配包含指定字符的字段值。以下是两种常用方式: 1. **使用 `QueryWrapper`(传统方式)**: - 适用于字段名直接指定的场景。 - 代码示例: ```java QueryWrapper<User> wrapper = new QueryWrapper<>(); // 对name字段进行模糊查询,查找包含"张"的记录 wrapper.like("name", "张"); List<User> userList = userMapper.selectList(wrapper); ``` - 输出SQL:`SELECT * FROM user WHERE name LIKE '%张%'` 2. **使用 `LambdaQueryWrapper`(推荐,类型安全)**: - 通过Lambda表达式引用实体类属性,避免硬编码字段名错误。 - 代码示例(基于引用[2]的模糊查询实践): ```java LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>(); // 对phone字段模糊查询手机号包含"139"的记录 lambdaWrapper.like(User::getPhone, "139"); List<User> userList = userMapper.selectList(lambdaWrapper); ``` - 输出SQL:`SELECT * FROM user WHERE phone LIKE '%139%'` ### 二、进阶用法:自定义通配符位置 `like` 方法默认在值前后添加 `%`,但可通过其他方法调整: - **左模糊(后缀匹配)**:`likeLeft("name", "张")` → `name LIKE '%张'` - **右模糊(前缀匹配)**:`likeRight("name", "张")` → `name LIKE '张%'` - **自定义模糊逻辑**: ```java LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.apply("name LIKE {0}", "%" + escapeWildcards(input) + "%"); // 手动拼接 ``` ### 三、关键注意事项:通配符转义与安全 模糊查询中,用户输入若包含 `%` 或 `_` 可能引发全表扫描(性能灾难)或数据泄露(引用[1])。例如: - 输入 `"张%"` ,SQL变为 `LIKE '张%'`,可能返回远超预期的结果。 - **解决方案**: - **应用层转义**:在Java代码中预处理输入值,转义 `%` 和 `_`: ```java public String escapeWildcards(String input) { return input.replace("%", "\\%").replace("_", "\\_"); } // 使用示例 lambdaWrapper.like(User::getName, escapeWildcards(userInput)); ``` - **拦截器实现**(推荐,引用[1]):开发自定义拦截器,自动转义所有模糊查询参数: ```java @Interceptor public class EscapeInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { Object[] args = invocation.getArgs(); for (int i = 0; i < args.length; i++) { if (args[i] instanceof String) { args[i] = ((String) args[i]).replace("%", "\\%").replace("_", "\\_"); } } return invocation.proceed(); } } ``` 需在MyBatis配置中注册此拦截器以确保全局生效。 ### 四、结合分页与其他查询 模糊查询常与其他功能联用(引用[2][5]): - **分页查询集成**:添加分页拦截器后,模糊查询可与分页结合: ```java // 配置分页拦截器(引用[5]) @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } // 模糊查询+分页示例 Page<User> page = new Page<>(1, 10); // 第1页,每页10条 LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.like(User::getName, "张"); Page<User> result = userMapper.selectPage(page, wrapper); ``` - **多条件组合**:模糊查询可与 `eq`(等值查询)、`ne`(查询)等组合: ```java LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(); wrapper.like(User::getName, "张") .eq(User::getStatus, 1); // 状态为启用的用户 ``` ### 五、常见问题与优化 - **性能问题**:模糊查询 `LIKE '%value%'` 无法使用索引,建议: - 对大表改用 `LIKE 'value%'`(右模糊),可利用索引。 - 添加查询条件限制范围(如间区间)。 - **多表模糊查询**:若需关联表,可使用插件如 `mybatis-plus-join`(引用[3]),但需注意复杂度。 ###
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值