没有传递过滤器参数时的Spring Data QuerydslBinderCustomizer

时间:2018-04-18 07:40:17

标签: spring-data spring-data-jpa spring-data-rest querydsl

我正在实现一个Repository,它实现了QuerydslBinderCustomizer,以帮助从url过滤器参数创建Predicates。就是这样

@NoRepositoryBean
public interface TableRepository<T extends TableEntity, S extends EntityPathBase<T>> extends PagingAndSortingRepository<T, UUID>, QuerydslPredicateExecutor<T>, QuerydslBinderCustomizer<S> {
    @Override
    default void customize(@NonNull QuerydslBindings bindings, @NonNull S root) {
        bindings.bind(String.class).all((MultiValueBinding<StringPath, String>) (path, values) -> {
            BooleanBuilder predicate = new BooleanBuilder();
            values.forEach(value -> predicate.or(path.containsIgnoreCase(value)));
            return Optional.of(predicate);
        });
    }
}

我的个人实体存储库正在扩展,如

public interface UserRepository extends TableRepository<User, QUser> {
}

这会产生端点http://localhost:port/users。事情很好,我可以提出http://localhost:port/users?name="somename"等请求。

现在,我正在实现软删除,我不想在查询时返回软删除的记录。我打算为此编辑customize方法

default void customize(@NonNull QuerydslBindings bindings, @NonNull S root) {
        bindings.bind(String.class).all((MultiValueBinding<StringPath, String>) (path, values) -> {
            BooleanBuilder predicate = new BooleanBuilder();
            values.forEach(value -> predicate.or(path.containsIgnoreCase(value)));
            // If path does not have delete flag, add deleted=false to the predicate
            return Optional.of(predicate);
        });
    }

但是当没有任何参数(即http://localhost:port/users)对端点进行调用时会出现问题。在这种情况下,bindings.bind()会被执行但BooleanBuilder predicate = new BooleanBuilder();部分却不会执行。因此,我无法添加所需的谓词来过滤掉软删除的记录。怎么办?

我可能会以错误的方式过滤删除的记录。还有更好的选择吗?

编辑:根据要求,我正在关联基本存储库https://github.com/SayakMukhopadhyay/demo-querydsl

1 个答案:

答案 0 :(得分:1)

所以我想您现在已经找到了解决方案。 但是对于那些试图获得某种“默认谓词”的人来说,这里是一个潜在的解决方案。

就像您的情况一样,我们也进行了软删除,并希望在默认情况下排除它们,除非特别要求。

首先,您不能在自定义方法中设置此项。 这些绑定仅在为条件传递值时触发。由于某些原因,当没有价值时,他们没有提供绑定。 他们可能有充分的理由这样做。 所以在这个方法中你只关心通过的标准。

我们在请求中处理默认值的方式是在调用 findAll 之前修改 Predicate。

控制器

控制器签名应该是这样的,带有一个谓词:

@GetMapping
public ResponseEntity<List<User>> searchUsers(
            @QuerydslPredicate(root = User.class, bindings = UserRepository.class) Predicate predicate) 

服务

您只需要检查谓词中是否包含条件, 如果没有,请自行添加。

if (!ExpressionUtils.extract(predicate).toString().contains("deleted =")) {
    predicate = new StringPath("deleted").eq("false").and(predicate);
}
userRepository.findAll(predicate);

如果不存在,应该添加条件,如果存在则忽略。

这显然是一个简化的表示,但想法就在那里。

希望这会有所帮助。