spring data jpa實現多條件查詢(分頁和不分頁)

目前的spring data jpa已經幫我們幹了CRUD的大部分活了,但如果有些活它幹不了(CrudRepository接口中沒定義),那麼只能由我們自己幹了。這裏要說的就是在它的框架裏,如何實現自己定製的多條件查詢。下面以我的例子說明一下:業務場景是我現在有張訂單表,我想要支持根據訂單狀態、訂單當前處理人和訂單日期的起始和結束時間這幾個條件一起查詢。

   先看分頁的,目前spring data jpa給我們做分頁的Repository是PagingAndSortingRepository,但它滿足不了自定義查詢條件,只能另選JpaRepository。那麼不分頁的Repository呢?其實還是它。接下來看怎麼實現:

  Repository:

import com.crocodile.springboot.model.Flow;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface FlowRepository extends JpaRepository<Flow, Long> {
    Long count(Specification<Flow> specification);

    Page<Flow> findAll(Specification<Flow> specification, Pageable pageable);

    List<Flow> findAll(Specification<Flow> specification);

}

  Service:

/**
     * 獲取結果集
     *
     * @param status
     * @param pageNo
     * @param pageSize
     * @param userName
     * @param createTimeStart
     * @param createTimeEnd
     * @return
     */
    public List<Flow> queryFlows(int pageNo, int pageSize, String status, String userName, Date createTimeStart, Date createTimeEnd) {
        List<Flow> result = null;

        // 構造自定義查詢條件
        Specification<Flow> queryCondition = new Specification<Flow>() {
            @Override
            public Predicate toPredicate(Root<Flow> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if (userName != null) {
                    predicateList.add(criteriaBuilder.equal(root.get("currentOperator"), userName));
                }
                if (status != null) {
                    predicateList.add(criteriaBuilder.equal(root.get("status"), status));
                }
                if (createTimeStart != null && createTimeEnd != null) {
                    predicateList.add(criteriaBuilder.between(root.get("createTime"), createTimeStart, createTimeEnd));
                }
                return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
            }
        };

        // 分頁和不分頁,這裏按起始頁和每頁展示條數爲0時默認爲不分頁,分頁的話按創建時間降序
        try {
            if (pageNo == 0 && pageSize == 0) {
                result = flowRepository.findAll(queryCondition);
            } else {
                result = flowRepository.findAll(queryCondition, PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "createTime"))).getContent();
            }
        } catch (Exception e) {
            LOGGER.error("--queryFlowByCondition-- error : ", e);
        }

        return result;
    }

上面我們可以看到,套路很簡單,就是兩板斧:先通過Specification對象定義好自定義的多查詢條件,我這裏的條件是當傳了當前用戶時,那麼將它加入到查詢條件中,不傳該參數自然就不加,同理,傳了訂單狀態的話那是通過相等來判斷,最後,如果傳了起始和結束時間,通過between來查在起始和結束之間的數據;第二板斧調用我們在Repository中定義好的findAll方法,如果分頁就用帶Pageable分頁對象參數的方法,不分頁不帶該參數即可。

  如果你的自定義查詢條件裏需要模糊查詢,比如我有個訂單ID要支持模糊查詢,也很簡單:

if (orderId!= null) {
      predicateList.add(criteriaBuilder.like(root.get("orderId"), "%" + orderId+ "%"));} 

最後我們看回到FlowRepository的第一個方法count,它是返回不分頁的多查詢的總記錄數的,套路也是一樣的:

/**
     * 查記錄數
     *
     * @param status
     * @param userName
     * @param createTimeStart
     * @param createTimeEnd
     * @return
     */
    public Long getCounts(String status, String userName, Date createTimeStart, Date createTimeEnd) {
        Long total = 0L;
        Specification<Flow> countCondition = new Specification<Flow>() {
            @Override
            public Predicate toPredicate(Root<Flow> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();
                if (userName != null) {
                    predicateList.add(criteriaBuilder.equal(root.get("currentOperator"), userName));
                }
                if (status != null) {
                    predicateList.add(criteriaBuilder.equal(root.get("status"), status));
                }
                if (createTimeStart != null && createTimeEnd != null) {
                    predicateList.add(criteriaBuilder.between(root.get("createTime"), createTimeStart, createTimeEnd));
                }
                return criteriaBuilder.and(predicateList.toArray(new Predicate[predicateList.size()]));
            }
        };

        try {
            total = flowRepository.count(countCondition);
        } catch (Exception e) {
            LOGGER.error("--getCountsByCondition-- error: ", e);
        }
        return total;
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章