如何从Spring QueryDSL Predicate中提取表达式路径与值?
如何从Spring自动生成的QueryDSL Predicate中提取路径和对应值?
当然可以实现!你已经走对了一半——提取表达式路径的方法没问题,要拿到路径对应的匹配值,自定义QueryDSL的Visitor接口是正确的方向,就像你找到的ConstantExtractor方案一样,我来帮你把整个流程串起来:
1. 回顾你的场景
你通过Spring的@QuerydslPredicate注解在Controller中自动生成Predicate:
public ResponseEntity<MyDTO> agentWinLoseSA( @QuerydslPredicate(root = MyObject.class) Predicate filter, Pageable pageable) throws URISyntaxException
前端通过查询参数(比如https://myhost:port/api/myobj?person.name=Dave)传入条件,现在需要从生成的filter中解析出person.name=Dave这样的路径-值对。
2. 路径提取(你已实现的部分)
先通过PredicateOperation提取表达式,再用PathExtractor拿到路径字符串:
List<Expression<?>> expressions = ((PredicateOperation) filter).getArgs(); for (Expression<?> expression : expressions) { String expressionPath = expression.accept(PathExtractor.DEFAULT, null).toString(); // 接下来我们要在这里提取对应的值 }
3. 自定义ConstantExtractor提取匹配值
你找到的这个ConstantExtractor完美解决了值提取的问题,它通过遍历QueryDSL表达式树,定位到常量值节点:
import com.querydsl.core.types.Constant; import com.querydsl.core.types.Expression; import com.querydsl.core.types.FactoryExpression; import com.querydsl.core.types.Operation; import com.querydsl.core.types.ParamExpression; import com.querydsl.core.types.Path; import com.querydsl.core.types.SubQueryExpression; import com.querydsl.core.types.TemplateExpression; import com.querydsl.core.types.Visitor; import java.util.List; public class ConstantExtractor implements Visitor<Constant<?>, Void> { public static final ConstantExtractor DEFAULT = new ConstantExtractor(); private ConstantExtractor() { } @Override public Constant<?> visit(Constant<?> expr, Void context) { return expr; } @Override public Constant<?> visit(FactoryExpression<?> expr, Void context) { return visit(expr.getArgs()); } @Override public Constant<?> visit(Operation<?> expr, Void context) { return visit(expr.getArgs()); } @Override public Constant<?> visit(ParamExpression<?> expr, Void context) { return null; } @Override public Constant<?> visit(Path<?> expr, Void context) { return null; } @Override public Constant<?> visit(SubQueryExpression<?> expr, Void context) { return null; } @Override public Constant<?> visit(TemplateExpression<?> expr, Void context) { return visit(expr.getArgs()); } private Constant<?> visit(List<?> exprs) { for (Object e : exprs) { if (e instanceof Expression) { Constant<?> constant = ((Expression<?>) e).accept(this, null); if (constant != null) { return constant; } } } return null; } }
4. 结合路径和值提取的完整示例
把两者结合起来,就能拿到完整的路径-值对了:
List<Expression<?>> expressions = ((PredicateOperation) filter).getArgs(); for (Expression<?> expression : expressions) { // 提取路径 String expressionPath = expression.accept(PathExtractor.DEFAULT, null).toString(); // 提取对应的值 Constant<?> constant = expression.accept(ConstantExtractor.DEFAULT, null); Object value = constant != null ? constant.getConstant() : null; // 输出结果,比如 person.name = Dave System.out.printf("%s = %s%n", expressionPath, value); }
这个方案能完美解析@QuerydslPredicate生成的简单等值条件,如果你需要处理更复杂的逻辑(比如范围查询、多条件组合),只需要在ConstantExtractor或者遍历逻辑中做相应扩展即可。
内容的提问来源于stack exchange,提问作者dim1902
相关产品推荐
相关产品推荐

