如何在 QueryDSL Web 中使用不同的运算符?

sza*_*kel 3 spring querydsl spring-data-jpa spring-boot

我在我的 Spring Boot 项目中使用QueryDSL并计划使用 Spring 的网络支持(当前查询 dsl web docs)。问题是,我找不到有关使用不同运算符的任何信息。如何定义not equalsmatches regex操作?乍一看,它所做的只是将您的?fieldname=value格式GET请求转换为您在存储库中设置的预定义操作。我可以以某种方式扩展它以允许对同一字段进行多次操作吗?

例子。:

目前我可以Predicate通过传递 URL 参数来获取 QueryDsl ,例如?user.company.id=1

@Controller
class UserController {

  @Autowired UserRepository repository;

  @RequestMapping(value = "/", method = RequestMethod.GET)
  Page<User> getUsers(@QuerydslPredicate(root = User.class) Predicate predicate,    
          Pageable pageable) {

    return repository.findAll(predicate, pageable);
  }
}
Run Code Online (Sandbox Code Playgroud)

但正如我链接的文档所述,我只能为某个字段定义一个操作。如果我想要用户,从哪里user.lastName开始并且仍然可以查询完全匹配怎么办?(?lastName=Xyz,contains?lastName=Xyz,equals可能)

QuerydslBinderCustomizer每场的基础上定义了一些操作,但你只能定义如何处理特定领域,有没有可能添加多个操作。

也许我不能用 QueryDSL 做到这一点,但是通常在 Spring Boot 中,您如何将过滤器应用于搜索查询?

Der*_*lai 6

我正在做类似的事情。尽管当我尝试执行更复杂的操作时面临一些限制。我在一些步骤中做了什么:

  • 创建一个MyBinderCustomizer<T extends EntityPath<?>>扩展的新接口QuerydslBinderCustomizer<QUser>(注意 User 的 Q,您需要 QueryDSL 自动生成的类而不是您的实体)。
  • 实施customize方法。例如:

@Override
public default void customize(QuerydslBindings bindings, T root) {
    bindings.bind(String.class).all(MyBinderCustomizer::applyStringComparison);
}

static BooleanExpression applyStringComparison(Path<String> path, Collection<? extends String> strings) {
    BooleanExpression result = null;

    for (String s : strings) {
        try {
            final String[] parts = s.split(",");
            final String operator = parts[0];
            final String value = parts.length > 1 ? parts[1] : null;

            final Method method = Arrays.stream(path.getClass().getMethods())
                    .filter(m -> operator.equals(m.getName()))
                    .filter(m -> BooleanExpression.class.equals(m.getReturnType()))
                    .filter(m -> m.getParameterTypes().length == (value == null ? 0 : 1))
                    .filter(m -> value == null || m.getParameterTypes()[0].equals(String.class) || m.getParameterTypes()[0].equals(Object.class))
                    .findFirst().get();

            final BooleanExpression be;
            if (value == null) {
                be = (BooleanExpression) method.invoke(path);
            } else {
                be = (BooleanExpression) method.invoke(path, value);
            }

            result = result == null ? be : result.and(be);

        } catch (Throwable t) {
            throw new RuntimeException(t);
        }
    }

    return result;

}
Run Code Online (Sandbox Code Playgroud)
  • 请注意,您应该更改值/运算符顺序,以便您可以调用像 isNull 这样的无值运算符。
  • 您的存储库必须扩展MyBinderCustomizer<QUser>(再次注意 Q)。

这将让您使用这些操作:

    public BooleanExpression StringExpression.like(java.lang.String)
    public BooleanExpression StringExpression.notLike(java.lang.String)
    public BooleanExpression StringExpression.notEqualsIgnoreCase(java.lang.String)
    public BooleanExpression StringExpression.containsIgnoreCase(java.lang.String)
    public BooleanExpression StringExpression.likeIgnoreCase(java.lang.String)
    public BooleanExpression StringExpression.startsWithIgnoreCase(java.lang.String)
    public BooleanExpression StringExpression.endsWithIgnoreCase(java.lang.String)
    public BooleanExpression StringExpression.equalsIgnoreCase(java.lang.String)
    public BooleanExpression StringExpression.startsWith(java.lang.String)
    public BooleanExpression StringExpression.endsWith(java.lang.String)
    public BooleanExpression StringExpression.matches(java.lang.String)
    public BooleanExpression StringExpression.contains(java.lang.String)

    公共布尔表达式 StringExpression.isEmpty()
    公共布尔表达式 StringExpression.isNotEmpty()
    公共布尔表达式 SimpleExpression.isNull()
    公共布尔表达式 SimpleExpression.isNotNull()
    公共布尔表达式 SimpleExpression.ne(java.lang.Object)
    公共布尔表达式 SimpleExpression.eq(java.lang.Object)


Gee*_*aat 5

春季数据QueryDSL值算图书馆延伸春数据QueryDSL网络支持与运营商不仅字符串领域,还数和枚举领域。它需要一些特殊的配置,使其成为非字符串下地干活,为解释在这里

值运算符在基于字符串的属性/字段上无缝工作。然而,这些运算符不适用于 Number 或 Enum 等非字符串值,因为默认情况下QuerydslPredicateArgumentResolver解析 annotation QuerydslPredicate,用于注释 RESTful 方法(又名 RestController 方法)上的搜索处理方法,根据指导设计原则执行强类型Querydsl,即它尝试将从 HTTP 请求接收的值转换为相应 Q-Classes 中定义的确切类型。这在没有值运算符的情况下运行良好,并且符合 Querydsl 允许类型安全查询的承诺,但是阻碍了值运算符实现他们的技巧。

该库提供了两种方法来使运算符适用于非字符串字段:

  1. 从查询参数中提取运算符的过滤器,因此查询参数仍然可以转换为其对应的类型(使用强类型)
  2. 替换 ConversionService 中的QuerydslPredicateArgumentResolver所有查询参数都被视为字符串(失去强类型)

这两种方法都有很好的文档记录,以及它们的用例和缺点。

我目前正在评估方法 1,因为它适合我们的用例,但我需要扩展它以适应 DateTime 字段和一些自定义运算符。

  • 该库的 4.0.0 版本已发布,它也可以处理日期(时间)字段。例如,您可以使用以下查询字符串:`/users/search?profile.dateOfBirth=lt(1/1/1970)&amp;profile.dateOfBirth=and(gt(12/31/1959))`。请参阅 [UserSearchIT 测试](https://bitbucket.org/gt_tech/spring-data-querydsl-value-operators/src/master/querydsl-value-operators/src/test/java/org/bitbucket/gt_tech/spring /data/querydsl/value/operators/integration/tests/UsersSearchIT.java)了解更多示例。 (3认同)