简体   繁体   English

QueryDSL - 谓词转换:更改根路径并检查结构

[英]QueryDSL - Predicate conversion : change root path and check structure

I'm using this awesome library, but I have a problem.我正在使用这个很棒的库,但是我遇到了问题。

I'm implementing a DTO pattern, so I use another project to convert automaticaly an EJB to a DTO using naming conventions.我正在实现 DTO 模式,因此我使用另一个项目使用命名约定将 EJB 自动转换为 DTO。

Then, I want to query the DTO and getting the real result (EJB query).然后,我想查询 DTO 并获得真正的结果(EJB 查询)。

I implemented QueryDSL with JPAAnnotationProcessor on my ENTITIES, and the QuerydslAnnotationProcessor on my DTOs.我在我的实体上使用 JPAAnnotationProcessor 实现了 QueryDSL,在我的 DTO 上实现了 QuerydslAnnotationProcessor。

For example :例如 :

  • An entity User(Long Id, String username, Site site)实体用户(长 ID、字符串用户名、站点站点)
  • A DTO UserDto(Long id, String username, String siteName)一个 DTO UserDto(Long id, String username, String siteName)

Converting objects is good, "siteName" automatically match "site.name".转换对象很好,“siteName”自动匹配“site.name”。

And so, I put a QueryDSL Query like: userDto.id.gt(20).and(userDto.username.like("a%")).and(userDto.siteName.like("%b"));因此,我放置了一个 QueryDSL 查询,如: userDto.id.gt(20).and(userDto.username.like("a%")).and(userDto.siteName.like("%b"));

I'm looking for a way to build the corresponding entity query我正在寻找一种方法来构建相应的实体查询

The only idea I got is to :我唯一的想法是:

  • Clone the Query克隆查询
  • Change the path "userDto" to "user"将路径“userDto”更改为“user”
  • Verify each predicate to know if the property exists and if the type is matching验证每个谓词以了解属性是否存在以及类型是否匹配

Any way to do that or to reach my goal?有什么办法可以做到这一点或达到我的目标?

Thanks谢谢

You will need to convert expressions in general.您通常需要转换表达式。 With a custom ReplaceVisitor you can for example override visit(Path expr, @Nullable Void context)使用自定义 ReplaceVisitor,您可以例如覆盖访问(路径表达式,@Nullable Void 上下文)

A generic way to do the path replacements would be to use a Map map to define the replacements:进行路径替换的通用方法是使用 Map 地图来定义替换:

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

You can use your visitor like this:您可以像这样使用您的访问者:

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

Since this is still relevant and undocumented functionality, and since Timo's answer, while helpful, is very cryptic, here's how to do it:由于这仍然是相关且未记录的功能,并且由于 Timo 的回答虽然有用,但非常神秘,因此这里是如何做到的:

First, extend ReplaceVisitor :首先,扩展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);
        }
    }
}

Then use it like this:然后像这样使用它:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM