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

问题描述 投票:2回答:2

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

例。:

目前我可以通过传递URL参数来获取QueryDsl qazxsw poi,例如qazxsw poi:

Predicate

但是,正如我链接的文档所述,我只能为某个字段定义单个操作。如果我想要用户,?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); } } user.lastName也许)

?lastName=Xyz,contains定义了每个字段的操作,但是您只能定义如何处理该特定字段,不可能添加多个操作。

也许我不能用QueryDSL做到这一点,但是一般在Spring启动时如何将过滤器应用于搜索查询?

spring spring-boot spring-data-jpa querydsl
2个回答
3
投票

我正在做那样的事情。虽然我尝试做更复杂的动作时遇到了一些限制。我在一些步骤中所做的事情:

  • 创建一个扩展?lastName=Xyz,equals的新接口QuerydslBinderCustomizer(注意用户的Q,你想要QueryDSL自动生成的类而不是你的实体)。
  • 实施MyBinderCustomizer<T extends EntityPath<?>>方法。例如:

QuerydslBinderCustomizer<QUser>
  • 请注意,您应该更改值/运算符顺序,以便可以调用isNull之类的无值运算符。
  • 您的存储库必须扩展customize(再次注意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)

    public BooleanExpression StringExpression.isEmpty()
    public BooleanExpression StringExpression.isNotEmpty()
    public BooleanExpression SimpleExpression.isNull()
    public BooleanExpression SimpleExpression.isNotNull()
    public BooleanExpression SimpleExpression.ne(java.lang.Object)
    public BooleanExpression SimpleExpression.eq(java.lang.Object)


2
投票

@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; } 库扩展MyBinderCustomizer<QUser>不仅包含字符串字段,还包括Number和Enum字段。它需要一些特殊的配置才能使它适用于非String字段,如Spring Data QueryDSL Value Operators所述:

值运算符在基于字符串的属性/字段上无效工作。但是这些运算符不能很好地处理非字符串值,如Number或Enum,因为默认情况下Spring Data QueryDSL web support解析注释here,用于在RESTful方法(也就是RestController方法)上注释搜索处理方法,根据指导执行强类型Querydsl的设计原则,即它试图将从HTTP请求接收的值转换为在相应的Q-Class中定义的精确类型。这在没有值运算符的情况下运行良好,并且与Querydsl承诺允许类型安全查询但是阻碍值运算符执行其技巧的路径。

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

  1. 一个从查询参数中提取运算符的过滤器,因此查询参数仍然可以转换为相应的类型(使用强类型)
  2. 替换QuerydslPredicateArgumentResolver中的ConversionService,以便将所有查询参数视为String(丢失强类型)

两种方法都有详细记录,以及它们的用例和缺点。

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

© www.soinside.com 2019 - 2024. All rights reserved.