You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MyBatis中使用注解实现条件Where子句?

MyBatis注解实现条件Where子句查询的参数绑定问题

现有代码及问题

Service层代码

public List<ApplicationConfig> find(@RequestBody String type){
    List<WhereClauseParams> conditions = new ArrayList<>();
    WhereClauseParams condition = new WhereClauseParams("type", type);
    conditions.add(condition);
    return applicationConfigRepository.find(conditions);
}

public List<ApplicationConfig> findById(@RequestBody String id){
    List<WhereClauseParams> conditions = new ArrayList<>();
    WhereClauseParams condition = new WhereClauseParams("id", id);
    conditions.add(condition);
    return applicationConfigRepository.find(conditions);
}

自定义WhereClauseParams类

public class WhereClauseParams {
    private String column;
    private String sqlOperator = "=";
    private Object value;
    // 包含对应的getter、setter方法与构造方法
}

Mapper接口代码

@Repository
@Mapper
public interface ApplicationConfigRepository {
    @Select("<script>" +
            "select id, name, type, isActive, createdBy, createdOn, updatedBy, updatedOn " +
            "from application_config " +
            "where 1=1 " +
            "<if test=\"type!=null\"> " +
            " and type=#{type} " +
            " </if>" +
            "<if test=\"id!=null\"> " +
            " and id=#{id} " +
            " </if>" +
            "</script>")
    public List<ApplicationConfig> find(List<WhereClauseParams> params);
}

首次报错信息

org.apache.ibatis.binding.BindingException: Parameter 'type' not found. Available parameters are [collection, list, params]
...(省略完整栈信息)

尝试将Mapper中的条件改为params.type!=null,问题未解决。

修改后的尝试

修改后的Service层

public List<ApplicationConfig> find(@RequestBody String type){
    List<WhereClauseParams> conditions = new ArrayList<>();
    WhereClauseParams condition = new WhereClauseParams("type", type);
    conditions.add(condition);
    return applicationConfigRepository.find(Map.of("type", type));
}

public List<ApplicationConfig> findById(@RequestBody String id){
    List<WhereClauseParams> conditions = new ArrayList<>();
    WhereClauseParams condition = new WhereClauseParams("id", id);
    conditions.add(condition);
    return applicationConfigRepository.find(Map.of("id", id));
}

修改后的Mapper接口

@Select("<script>" +
        "select id, name, type, isActive, createdBy, createdOn, updatedBy, updatedOn " +
        "from application_config " +
        "where 1=1 " +
        "<if test=\"params.type!=null\"> " +
        " and type=#{params.type} " +
        " </if>" +
        "<if test=\"params.id!=null\"> " +
        " and id=#{params.id} " +
        " </if>" +
        "</script>")
public List<ApplicationConfig> find(Map params);

新报错信息

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 'params.type!=null'. Cause: org.apache.ibatis.ognl.OgnlException: source is null for getProperty(null, "type")
...(省略完整栈信息)

解决方案

方案1:简化Map参数传递

修改Mapper的SQL表达式,去掉多余的params.前缀,因为传递的Map直接包含type、id等键:

@Repository
@Mapper
public interface ApplicationConfigRepository {
    @Select("<script>" +
            "select id, name, type, isActive, createdBy, createdOn, updatedBy, updatedOn " +
            "from application_config " +
            "where 1=1 " +
            "<if test=\"type!=null\"> " +
            " and type=#{type} " +
            " </if>" +
            "<if test=\"id!=null\"> " +
            " and id=#{id} " +
            " </if>" +
            "</script>")
    public List<ApplicationConfig> find(Map<String, Object> params);
}

Service层保持现有传递Map的逻辑即可,无需额外修改。

方案2:复用WhereClauseParams实现动态多条件

如果需要支持多条件组合查询,保留WhereClauseParams设计,用MyBatis的<foreach>遍历条件列表:

  1. 修改Mapper接口,用@Param明确参数名:
@Repository
@Mapper
public interface ApplicationConfigRepository {
    @Select("<script>" +
            "select id, name, type, isActive, createdBy, createdOn, updatedBy, updatedOn " +
            "from application_config " +
            "where 1=1 " +
            "<foreach collection='conditions' item='condition' separator=' and '>" +
            " ${condition.column} ${condition.sqlOperator} #{condition.value} " +
            "</foreach>" +
            "</script>")
    public List<ApplicationConfig> find(@Param("conditions") List<WhereClauseParams> conditions);
}
  • 注意:column和sqlOperator用${}(直接拼接SQL,需确保参数安全,避免注入),value用#{}(预编译,防止注入)。
  1. Service层恢复最初传递conditions列表的逻辑即可。

方案3:单条件场景简化实现

如果只是单条件查询(按type或id),直接用@Param标注单个参数:

@Repository
@Mapper
public interface ApplicationConfigRepository {
    @Select("<script>" +
            "select id, name, type, isActive, createdBy, createdOn, updatedBy, updatedOn " +
            "from application_config " +
            "where 1=1 " +
            "<if test='type != null'> and type = #{type} </if>" +
            "<if test='id != null'> and id = #{id} </if>" +
            "</script>")
    List<ApplicationConfig> find(@Param("type") String type, @Param("id") String id);
}

Service层调用时传递对应参数,比如find(type, null)或find(null, id)。

内容的提问来源于stack exchange,提问作者Abhishek Acharya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:33:21