亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用條件實現搜索過濾器

使用條件實現搜索過濾器

慕標5832272 2022-11-02 10:06:03
我想用幾個子條件實現搜索功能。我試過這個:    @GetMapping("find")    public Page<PaymentTransactionsDTO> getAllBySpecification(            @And({                    @Spec(path = "name", spec = LikeIgnoreCase.class),                    @Spec(path = "unique_id", spec = LikeIgnoreCase.class),                    @Spec(path = "createdAt", params = "from", spec = GreaterThanOrEqual.class),                    @Spec(path = "createdAt", params = "to", spec = LessThanOrEqual.class)            }) Specification<PaymentTransactions> specification,            Pageable pageable    ) {                return transactionService.getAllBySpecification(specification, pageable));           }存儲庫:      @Override      public Page<PaymentTransactions> getAllBySpecification(final Specification<PaymentTransactions> specification, final Pageable pageable) {          return dao.findAll(specification, pageable);      }目前此請求正在運行:GET /api/transactions/find?unique_id=22&page=0&size=10 但我也想實現這些額外的搜索條件,不僅發送基本搜索unique_id:start with =end with contains使用https://github.com/tkaczmarzyk/specification-arg-resolver有沒有辦法發送額外的子條件?我一般找不到這個問題的解決方案,發送這些值的最佳做法是什么?
查看完整描述

1 回答

?
森欄

TA貢獻1810條經驗 獲得超5個贊

如果您想創建非常特殊的過濾器,我相信您應該從發明搜索界面開始。例如像這樣:


GET /models?name=eq(john smith)&createdAt=between(2019-01-01,2019-01-31)

GET /models?name=like(sm)&createdAt=from(2019-01-01)

GET /models?name=sw(john)&createdAt=to(2019-01-31)

之后,您將能夠嘗試實施它。


IMO 解決此類任務的最佳方法是使用 Spring Data JPA Specifications(和 JPA Criteria API)。例如:


1)讓我們創建一個為我們的實體Filter實現的類:SpecificationModel


@Value

public class ModelFilter implements Specification<Model> {


    private String name;

    private String createdAt;


    @Override

    public Predicate toPredicate(Root<Model> root, CriteriaQuery<?> query, CriteriaBuilder builder) {


        List<Predicate> predicates = new ArrayList<>();


        // Prepare predicates and fill the list with them...


        return builder.and(predicates.toArray(new Predicate[0]));

    }

}

2)然后創建一個控制器方法:


@GetMapping

public List<Model> getAllByFilter(ModelFilter filter) {

    return repo.findAll(filter); 

}

剩下要做的就是準備我們的謂詞))


為此,我們可以先創建一個方便的“謂詞生成器”界面:


@FunctionalInterface

interface PredicateBuilder<T> {


    Optional<Predicate> get(String fieldName, String value, Root<T> root, CriteriaBuilder builder);


    static Matcher getMatcher(String op, String value) {

        return getMatcher(op, value, "(.+)");

    }


    static Matcher getMatcher(String op, String value, String pattern) {

        return Pattern.compile(op + "\\(" + pattern + "\\)").matcher(value);

    }

}

然后嘗試制作我們的謂詞:


平等的


PredicateBuilder<Model> eq = (fieldName, value, root, cb) -> {

    Matcher m = getMatcher("eq", value);

    if (m.matches()) {

        return Optional.of(cb.equal(cb.upper(root.get(fieldName)), m.group(1).toUpperCase()));

    } else {

        return Optional.empty();

    }

};

喜歡


PredicateBuilder<Model> like = (fn, value, root, cb) -> {

    Matcher m = getMatcher("like", value);

    if (m.matches()) {

        return Optional.of(cb.like(cb.upper(root.get(fn)), "%" + m.group(1).toUpperCase() + "%"));

    } else {

        return Optional.empty();

    }

};

從...開始


PredicateBuilder<Model> sw = (fn, value, root, cb) -> {

    Matcher m = getMatcher("sw", value);

    if (m.matches()) {

        return Optional.of(cb.like(cb.upper(root.get(fn)), m.group(1).toUpperCase() + "%"));

    } else {

        return Optional.empty();

    }

};

之間


PredicateBuilder<Model> between = (fn, value, root, cb) -> {

    Matcher m = getMatcher("between", value, "(.+)\\s*,\\s*(.+)");

    if (m.matches()) {

        LocalDate from = LocalDate.parse(m.group(1));

        LocalDate to = LocalDate.parse(m.group(2));

        return Optional.of(cb.between(root.get(fn), from, to));

    } else {

        return Optional.empty();

    }

};


PredicateBuilder<Model> from = (fn, value, root, cb) -> {

    Matcher m = getMatcher("from", value);

    if (m.matches()) {

        LocalDate from = LocalDate.parse(m.group(1));

        return Optional.of(cb.greaterThanOrEqualTo(root.get(fn), from));

    } else {

        return Optional.empty();

    }

};


PredicateBuilder<Model> to = (fn, value, root, cb) -> {

    Matcher m = getMatcher("to", value);

    if (m.matches()) {

        LocalDate to = LocalDate.parse(m.group(1));

        return Optional.of(cb.lessThanOrEqualTo(root.get(fn), to));

    } else {

        return Optional.empty();

    }

};

剩下的只是完成Filter課程:


@Value

public class ModelFilter implements Specification<Model> {


    private String name;

    private String createdAt;


    PredicateBuilder<Model> eq = ... ;

    PredicateBuilder<Model> like = ... ;

    PredicateBuilder<Model> sw = ... ;

    PredicateBuilder<Model> between = ... ;

    PredicateBuilder<Model> from = ... ;

    PredicateBuilder<Model> to = ... ;


    @Override

    public Predicate toPredicate(Root<Model> root, CriteriaQuery<?> query, CriteriaBuilder builder) {


        List<Predicate> predicates = new ArrayList<>();


        if (name != null) {

            eq.get("name", name, root, builder).ifPresent(predicates::add);

            like.get("name", name, root, builder).ifPresent(predicates::add);

            sw.get("name", name, root, builder).ifPresent(predicates::add);

        }


        if (createdAt != null) {

            between.get("createdAt", createdAt, root, builder).ifPresent(predicates::add);

            from.get("createdAt", createdAt, root, builder).ifPresent(predicates::add);

            to.get("createdAt", createdAt, root, builder).ifPresent(predicates::add);

        }


        return builder.and(predicates.toArray(new Predicate[0]));

    }

}

當然,這只是實現的一個例子。您可以創建自己需要的規范和謂詞的實現。這里的主要內容是:

  • 想出你的搜索界面

  • 制定您的“過濾器”規范

  • 準備好你需要的所有謂詞

  • 在控制器方法中使用過濾器規范


查看完整回答
反對 回復 2022-11-02
  • 1 回答
  • 0 關注
  • 95 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號