gpt4 book ai didi

jpa - 带有Querydsl的JPA谓词

转载 作者:行者123 更新时间:2023-12-03 13:42:23 25 4
gpt4 key购买 nike

我在应用程序中使用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字符串并创建新查询)?

谢谢

最佳答案

使用QueryDSL表达式Visitor返回JPA标准Expression并使用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);

关于jpa - 带有Querydsl的JPA谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36604230/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com