springData jpa多条件查询重写Specification的toPredicate方法

jpa2.0支持了Criteria查询,对应的接口是JpaSpecificationExecutor,我们可以利用Criteria实现动态查询

我们查看JpaSpecificationExecutor接口,发现这个接口里面的方法都需要Specification,JpaSpecificationExecutor接口方法代码如下:

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

然后Specification却只有一个方法:

Predicate toPredicate(Root 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 spec = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                List list = new ArrayList(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 select(String userName){
	 Specification spec = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                List list = new ArrayList(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 select(List status ){
	 Specification spec = new Specification() {
            @Override
            public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
                List list = new ArrayList(1);
                list.add(cb.equal(root.get(User_.id),1));
				Subquery subquery = query.subquery(Role.class);
                    Root 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 )
   

 

你可能感兴趣的:(java,springjpa)