当前位置: 首页 > 知识库问答 >
问题:

带有Querydsl的JPA谓词

陈高寒
2023-03-14

我在应用程序中使用Querydsl来大大改进查询数据库的代码。但是,我有一个来自外部服务的JPA谓词(javax.persistence.criteria.Predicate)。我想混合使用Querydsl和外部谓词创建的查询。例如:

// JPA Predicate from external service
Root<User> root = ...;
CriteriaBuilder cb = ...;
javax.persistence.criteria.Predicate externalPredicate = externalService.filterEmail(root, cb, "%@gmail.com");

// Create Querydsl predicate
BooleanExpression querydslExp = QUser.username.eq("foo");

// Mix predicates (this is what I need)
querydslExp.and(externalPredicate);

另一个解决方案是将Querydsl谓词转换为JPA谓词:

cb.and(querydslExp.toJpaPredicate(), externalPredicate);

有可能吗?如果是,我如何做到这一点?如果没有,是否有其他混合谓词的解决方案(比如将两者转换为SQL字符串并创建一个新查询)?

谢谢

共有1个答案

鲜于子琪
2023-03-14

这很可能使用QueryDSL表达式visitor来完成,该表达式返回JPA条件表达式并使用CriteriaBuilderCriteriaQuery作为上下文:

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object> query = criteriaBuilder.createQuery();

javax.persistence.criteria.Expression<?> result = expression.accept(new Visitor<javax.persistence.criteria.Expression<?>, CriteriaBuilder>() {
    @Override
    public javax.persistence.criteria.Expression<?> visit(Constant<?> expr, CriteriaBuilder context) {
        return context.literal(expr.getConstant());
    }

    @Override
    public javax.persistence.criteria.Expression<?> visit(FactoryExpression<?> expr, CriteriaBuilder context) {
        throw new UnsupportedOperationException();
    }

    @Override
    public javax.persistence.criteria.Expression<?> visit(Operation<?> expr, CriteriaBuilder context) {
        javax.persistence.criteria.Expression<?>[] arguments = new javax.persistence.criteria.Expression<?>[expr.getArgs().size()];
        for (int i = 0; i < expr.getArgs().size(); i++) {
            // Visit arguments recursively
            arguments[i] = expr.getArg(i).accept(this, context);
        }

        if (expr.getOperator() instanceof Ops) {
            switch ((Ops) expr.getOperator()) {
                // For example, add more...
                case EQ:
                    return context.equal(arguments[0], arguments[1]);
                default:
                    // Assuming expr.getOperator().name() as function here is not always enough,
                    // it would be better to use a switch on various operation types.
                    return context.function(expr.getOperator().name(), expr.getType(), arguments);
            }
        }

    }

    @Override
    public javax.persistence.criteria.Expression<?> visit(ParamExpression<?> expr, CriteriaBuilder context) {
        return context.parameter(expr.getType(), expr.getName());
    }

    @Override
    public javax.persistence.criteria.Expression<?> visit(Path<?> expr, CriteriaBuilder context) {
        if (expr.getMetadata().isRoot()) {
            // Get query root
            return query.getRoots().stream().filter(r -> r.getAlias().equals(expr.getMetadata().getName())).findAny().get();
        }

        // Get parent path
        javax.persistence.criteria.Path<?> parent = (javax.persistence.criteria.Path<?>) expr.getMetadata().getParent().accept(this, context);
        return parent.get(expr.getMetadata().getName());
    }

    @Override
    public javax.persistence.criteria.Expression<?> visit(SubQueryExpression<?> expr, CriteriaBuilder context) {
        // Defenitely possible
        throw new UnsupportedOperationException();
    }

    @Override
    public javax.persistence.criteria.Expression<?> visit(TemplateExpression<?> expr, CriteriaBuilder context) {
        // No real JPA equivalent exist. ORM-specifically there are possibilities.
        throw new UnsupportedOperationException();
    }
}, criteriaBuilder);
 类似资料:
  • 环境是Java、Spring-boot、Hibernat、QueryDSL、MySQL。 我有表结构 艾碧索 更新 为了澄清起见,支持UI视图的DTO包含“casename”属性。它是在将域对象转换为DTO时在服务层创建的:

  • 我正在使用查询DSL的Spring数据JPA,并试图在条件中使用求和函数,因为我正在使用分页,所以我必须首先获得计数。所以我有如下的Java代码:- 它创建这样的查询:- 我得到。 上述查询在中也不起作用,因为sum函数不能与count-in-where条件一起使用。当我必须先进行计数,然后再获取真实数据时,我不知道如何处理这样的问题。有人能帮我解决这个问题的方法吗。 请不要建议注释,因为我不能使

  • 我想优化一个queryDSL+Spring数据查询。目前我使用BooleanBuilder作为谓词,这很好,但是它连接了太多的表。我不需要表中的所有列,也不需要某些表。我相信使用投影会减少加入的表的数量。 那么,如何使QueryDSL连接表而不是从所有表中进行选择呢?我尝试优化查询是否正确?投影有意义吗?

  • 我需要@query的原因是应用基于身份验证主体的安全性。 存储库的完整代码:

  • 本文向大家介绍Prolog带有副作用的谓词,包括了Prolog带有副作用的谓词的使用技巧和注意事项,需要的朋友参考一下 示例 产生副作用的谓词离开了纯逻辑领域。例如: writeq/1 read/1 format/2 副作用是程序中无法推理的现象。例如,删除文件或在系统终端上输出。

  • 问题内容: 我使用Vlad Mihalcea的库来将SQL数组(在我的情况下为Postgresql)映射到JPA。然后,假设我有一个实体,例如。 适当的SQL是: 使用QueryDSL,我想获取包含所有给定标签的行。原始SQL可能是: (摘自:https : //www.postgresql.org/docs/9.1/static/functions- array.html ) 可以用QueryD