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

例。:

目前,我可以通过传递URL参数来获取QueryDsl 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?lastName=Xyz,equals

QuerydslBinderCustomizer定义每个字段的操作,但是您只能定义如何处理该特定字段,无法添加多个操作。

也许我无法使用QueryDSL进行此操作,但是通常在Spring Boot中如何将过滤器应用于搜索查询?

最佳答案

我正在做类似的事情。尽管在尝试执行更复杂的操作时遇到一些限制。我在某些步骤中所做的事情:


创建一个扩展MyBinderCustomizer<T extends EntityPath<?>>的新接口QuerydslBinderCustomizer<QUser>(请注意,“用户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;

}



请注意,您应该更改值/运算符的顺序,以便可以调用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)

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

08-28 14:26