【问题标题】:QueryDSL - Predicate conversion : change root path and check structureQueryDSL - 谓词转换:更改根路径并检查结构
【发布时间】:2025-12-12 08:45:01
【问题描述】:

我正在使用这个很棒的库,但我遇到了问题。

我正在实现 DTO 模式,因此我使用另一个项目使用命名约定将 EJB 自动转换为 DTO。

然后,我想查询 DTO 并获得真正的结果(EJB 查询)。

我在我的 ENTITIES 上使用 JPAAnnotationProcessor 实现了 QueryDSL,在我的 DTO 上实现了 QuerydslAnnotationProcessor。

例如:

  • 实体用户(长 ID、字符串用户名、站点站点)
  • DTO UserDto(Long id, String username, String siteName)

转换对象就好了,“siteName”自动匹配“site.name”。

所以,我输入了一个 QueryDSL 查询,例如:userDto.id.gt(20).and(userDto.username.like("a%")).and(userDto.siteName.like("%b"));

我正在寻找一种方法来构建相应的实体查询

我唯一的想法是:

  • 克隆查询
  • 将路径“userDto”更改为“user”
  • 验证每个谓词以了解属性是否存在以及类型是否匹配

有什么方法可以做到这一点或达到我的目标吗?

谢谢

【问题讨论】:

    标签: java dto predicate querydsl visitor-pattern


    【解决方案1】:

    您通常需要转换表达式。例如,使用自定义 ReplaceVisitor,您可以覆盖访问(路径表达式,@Nullable Void 上下文)

    进行路径替换的通用方法是使用地图地图来定义替换:

    if (map.contains(path)) {
        return map.get(path);
    } else {
        return super.visit(path, context);
    }
    

    你可以这样使用你的访问者:

    Expression transformedExpression = expr.accept(visitor, null);
    

    【讨论】:

      【解决方案2】:

      由于这仍然是相关且未记录的功能,并且由于 Timo 的回答虽然很有帮助,但非常神秘,以下是如何做到这一点:

      首先,扩展ReplaceVisitor

      private class CustomReplaceVisior extends ReplaceVisitor<Void> {
          @Override
          public Expression<?> visit(Path<?> path, @Nullable Void context) {
              // The map Timo mentioned to transform paths:
              Map<Path<?>, Path<?>> map = Map.of(
                  QUser.user.id, QUserDto.userDto.id,
                  QUser.user.name, QUserDto.userDto.name
              );
              if (map.contains(path)) {
                  return map.get(path);
              } else {
                  return super.visit(path, context);
              }
          }
      }
      

      然后像这样使用它:

      CustomReplaceVisior replaceVisitor = new CustomReplaceVisior();
      Predicate userPredicate = QUser.user.id.eq(2).and(QUser.user.name.eq("Somename"));
      Predicate userDtoPredicate = (Predicate) userPredicate.accept(replaceVisitor, null);
      

      【讨论】:

        最近更新 更多