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

是否存在对标Bean Validation的注解式动态查询生成方案?

是否存在对标Bean Validation的注解式动态查询生成方案?

作为常年跟业务代码打交道的开发者,估计不少人都跟我一样,发现参数校验和动态查询构造的代码逻辑简直如出一辙——都是围绕对象的属性做一堆非空/非空串判断,然后执行对应的逻辑,写多了真的是又冗余又容易漏。

先给大家举个直观的例子:

首先定义一个简单的User实体类:

public class User {
    private String name;
    private Integer age;
    // getters and setters
}

手动参数校验的代码

public void validate(User user) {
    if (user.getName() == null || user.getName().isBlank()) {
        throw new IllegalArgumentException("name can not be empty");
    }
    if (user.getAge() == null) {
        throw new IllegalArgumentException("age can not be empty");
    }
    if (user.getAge() < 18 || user.getAge() > 60) {
        throw new IllegalArgumentException("age should be between 18 and 60");
    }
    // business logic
}

动态查询的代码(两种常见写法)

第一种是用StringJoiner拼接SQL条件:

public static String buildWhere(UserQuery query, List<Object> argList) {
    StringJoiner where = new StringJoiner(" AND ", " WHERE ", " ");
    where.setEmptyValue(" ");
    if (query.getName() != null && !query.getName().isBlank()) {
        where.add("name LIKE ?");
        argList.add(query.getName());
    }
    if (query.getAge() != null) {
        where.add("age = ?");
        argList.add(query.getAge());
    }
    return where.toString();
}

第二种是用JPA的Specification:

public List<User> query(User query) {
    Specification<User> spec = (root, cq, cb) -> {
        List<Predicate> predicates = new ArrayList<>();
        if (query.getName() != null && !query.getNameLike().isBlank()) {
            predicates.add(cb.like(root.get("name"), " % " + query.getName() + " % "));
        }
        if (query.getAge() != null) {
            predicates.add(cb.eq(root.get("age"), query.getAge()));
        }
        //...
        return cb.and(predicates.toArray(new Predicate[0]));
    };
    return userRepository.findAll(spec);
}

你看,这些代码是不是长得几乎一模一样?都是重复的判断逻辑,只是后续执行的操作不同——校验是抛异常,查询是拼接条件。

而参数校验这块,我们早就有了**Jakarta Validation(原Bean Validation)**这种声明式的解决方案,只要给实体字段加注解就行,再也不用写一堆if:

public class User {
    @NotBlank
    private String name;
    @NotNull
    @Range(min = 18, max = 60)
    private Integer age;
    // getters and setters
}

那问题来了:有没有类似的注解式方案,能让我们用注解来定义动态查询的条件,比如像下面这样写查询参数类?

public class UserQuery {
    @Condition("name LIKE ?")
    private String name;
    @Condition("age = ?")
    private Integer age;
}

其实这类需求早就有成熟的实现了,很多ORM框架或者第三方库都提供了类似的注解式动态查询支持:

  • 比如MyBatis-Plus的@TableField配合LambdaQueryWrapper,或者它的@Query注解;
  • JPA生态里也有Querydsl、Spring Data JPA的@Query配合SpEL表达式,甚至一些第三方扩展库(比如Blaze-Persistence)提供了更丰富的注解式查询定义;
  • 还有一些轻量的工具库,专门做注解式动态SQL生成,通过自定义注解(比如你示例里的@Condition)配合反射来自动拼接查询条件。

核心思路都是跟Bean Validation一致:用注解声明规则,框架通过反射解析注解,自动执行对应的逻辑(这里是生成查询条件),从而避免重复的if判断代码,让代码更简洁易维护。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 09:04:32