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

2023年如何在JdbcClient/JdbcTemplate中处理SQL WHERE子句动态条件?

处理JdbcClient动态WHERE条件的替代方案

方案1:用条件列表+String.join构建WHERE子句

这种方式比直接拼接字符串更整洁,还能避免WHERE 1=1的冗余写法:

@GetMapping("/user")
public Iterable<User> listByConditions(@RequestParam(required = false) String name,
                                       @RequestParam(required = false) Integer sex) {
    MapSqlParameterSource params = new MapSqlParameterSource();
    List<String> whereClauses = new ArrayList<>();

    if (name != null) {
        whereClauses.add("`name` = :name");
        params.addValue("name", name);
    }
    if (sex != null) {
        whereClauses.add("`sex` = :sex");
        params.addValue("sex", sex);
    }

    StringBuilder sqlBuilder = new StringBuilder("""
            SELECT `id`, `name`, `sex`
            FROM `user`
            """);
    if (!whereClauses.isEmpty()) {
        sqlBuilder.append("WHERE ").append(String.join(" AND ", whereClauses));
    }
    sqlBuilder.append("""
            ORDER BY `id`
            """);

    return jdbcClient.sql(sqlBuilder.toString())
            .params(params)
            .query(User.class)
            .list();
}

把每个有效条件存进列表,最后统一拼接,逻辑清晰,也不会产生多余的SQL片段。

方案2:Spring 6.1+自带的动态SQL模板

如果你的项目用Spring 6.1及以上版本,JdbcClient支持直接在多行字符串里写动态SQL逻辑,语法和MyBatis类似但不用XML:

@GetMapping("/user")
public Iterable<User> listByConditions(@RequestParam(required = false) String name,
                                       @RequestParam(required = false) Integer sex) {
    return jdbcClient.sql("""
            SELECT `id`, `name`, `sex`
            FROM `user`
            <if name='name != null'>
                WHERE `name` = :name
                <if name='sex != null'>
                    AND `sex` = :sex
                </if>
            <else if name='sex != null'>
                WHERE `sex` = :sex
            </if>
            ORDER BY `id`
            """)
            .param("name", name)
            .param("sex", sex)
            .query(User.class)
            .list();
}

直接把条件判断嵌在SQL字符串里,完美适配你喜欢多行字符串的需求,不用手动拼接SQL片段。

方案3:Querydsl实现类型安全的动态查询

如果想避免手写SQL时的字段名拼写错误,可以用Querydsl和JdbcClient结合,实现类型安全的动态查询:

@GetMapping("/user")
public Iterable<User> listByConditions(@RequestParam(required = false) String name,
                                       @RequestParam(required = false) Integer sex) {
    QUser user = QUser.user;
    SQLQuery<User> query = new SQLQuery<>(new MySQLTemplates(), new JdbcConnectionProvider(dataSource))
            .select(user)
            .from(user);

    if (name != null) {
        query.where(user.name.eq(name));
    }
    if (sex != null) {
        query.where(user.sex.eq(sex));
    }
    query.orderBy(user.id.asc());

    // 提取生成的SQL和参数
    String sql = query.getSQL().getSQL();
    MapSqlParameterSource params = new MapSqlParameterSource();
    query.getSQL().getBindings().forEach(binding -> 
            params.addValue(binding.getVariable(), binding.getValue())
    );

    return jdbcClient.sql(sql)
            .params(params)
            .query(User.class)
            .list();
}

需要提前配置Querydsl生成实体对应的Q类,所有字段调用都是类型安全的,不会出现字段名写错的问题,适合复杂的动态查询场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:32:13