springData jpa多條件查詢重寫Specification的toPredicate方法

jpa2.0支持了Criteria查詢,對應的接口是JpaSpecificationExecutor,我們可以利用Criteria實現動態查詢

我們查看JpaSpecificationExecutor接口,發現這個接口裏面的方法都需要Specification,JpaSpecificationExecutor接口方法代碼如下:

T findOne(Specification<T> spec);
List<T> findAll(Specification<T> spec);
Page<T> findAll(Specification<T> spec, Pageable pageable);
List<T> findAll(Specification<T> spec, Sort sort);
long count(Specification<T> spec);

然後Specification卻只有一個方法:

Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

參數解釋:
CriteriaQuery接口:代表一個specific的頂層查詢對象,它包含着查詢的各個部分,比如:select 、from、where、group by、order by等

Root接口:代表Criteria查詢的根對象,Criteria查詢的查詢根定義了實體類型,能爲將來導航獲得想要的結果,它與SQL查詢中的FROM子句類似

CriteriaBuilder是Predicate實例的工廠,通過調用CriteriaBuilder 的條件方法( equal,notEqual, gt, ge,lt, le,between,like等)創建Predicate對象。

下面說幾個簡單的例子:

demo1:

//代碼:
Specification<User> spec = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<Predicate>(1);
                list.add(cb.equal(root.get(User_.id),1));
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        };
        return spec;
}
//sql:
    select * from user where id = 1

demo2:

//代碼
public Specification<User> select(String userName){
	 Specification<User> spec = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<Predicate>(1);
                list.add(cb.equal(root.get(User_.id),1));
				if(!StringUtils.isEmpty(userName)){
					list.add(cb.equal(root.get(User_.userName),userName));
				};
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        };
        return spec;
	}
}
//sql
   當userName不爲空 select * from user where id = 1 and user_name = :userName
   當userName爲空 select * from user where id = 1

demo3:

//代碼
public Specification<User> select(List<Integer> status ){
	 Specification<User> spec = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<Predicate>(1);
                list.add(cb.equal(root.get(User_.id),1));
				Subquery<Role> subquery = query.subquery(Role.class);
                    Root<Role> subRoot = subquery.from(Role.class);
                    subquery.select(subRoot);
                    Predicate p = cb.equal(subRoot.get(Role_.id), root.get(User.role_id));
                    Predicate p2  =  subRoot.get(Role_.status).in(status);
                    subquery.where(p,p2);
                    list.add(cb.not(cb.exists(subquery)));
                }
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        };
        return spec;
	}
}
//sql
    select * from user a where id = 1 and not exists( select * from role b where b.id = a.role_id )
   

 

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