jpa的JpaSpecificationExecutor使⽤对象⾃定义sql条件;JPA的。。。
Specification的使⽤
Spring Data Jpa同样提供了类似Hibernated 的Criteria的查询⽅式,要使⽤这种⽅式只要继承JpaSpecificationExecutor,该接⼝提供了如下⼀些⽅法
T findOne(Specification<T> var1);
List<T>findAll(Specification<T> var1);
Page<T>findAll(Specification<T> var1, Pageable var2);
List<T>findAll(Specification<T> var1, Sort var2);
long count(Specification<T> var1);
⽐如继承JpaSpecificationExecutor的dao层
@Repository
public interface ShopUserMiddleRepository extends JpaRepository<ShopUserMiddleDO, Long>, JpaSpecificationExecutor<ShopUserMiddleDO>{
ShopUserMiddleDO findByUserId(Long userId);
}
该接⼝通过Specification来定义查询条件,很多朋友可能使⽤的⽅式都是基于SQL的,对这种⽅式可能不太习惯,其实就是类
似mybatisplus的wrapper,将sql条件⽤对象来实现。这⾥先简单看⼀下⽰例。
@Test
public void testSpecificaiton(){
List<Student> stus = studentSpecificationRepository.findAll(new Specification<Student>(){
@Override
public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder crit
eriaBuilder){
//("address")表⽰获取address这个字段名称(获取实体类的属性名对应的表字段名),like表⽰执⾏like查询,%zt%表⽰值
Predicate p1 = criteriaBuilder.("address"),"%zt%");
Predicate p2 = ("id"),3);
//将两个查询条件联合起来之后返回Predicate对象
return criteriaBuilder.and(p1,p2);
}
});
Assert.assertEquals(2,stus.size());
Assert.assertEquals("oo",(0).getName());
}
多个Specification组合
使⽤Specification的要点就是CriteriaBuilder,通过这个对象来创建条件,之后返回⼀个Predicate对象。这个对象中就有了相应的查询需求,我们同样可以定义多个Specification,之后通过Specifications对象将其连接起来。以下是⼀个⾮常典型的应⽤
@Test
public void testSpecificaiton2(){
//第⼀个Specification定义了两个or的组合
Specification<Student> s1 =new Specification<Student>(){
@Override
public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder){
Predicate p1 = criteriaBuilder.("id"),"2");
Predicate p2 = criteriaBuilder.("id"),"3");
(p1,p2);
}
};
//第⼆个Specification定义了两个or的组合
Specification<Student> s2 =new Specification<Student>(){
@Override
public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder){
Predicate p1 = criteriaBuilder.("address"),"zt%");
Predicate p2 = criteriaBuilder.("name"),"foo%");
(p1,p2);
}
};
//通过Specifications将两个Specification连接起来,第⼀个条件加where,第⼆个是and
List<Student> stus = studentSpecificationRepository.findAll(Specifications.where(s1).and(s2));
Assert.assertEquals(1,stus.size());
Assert.assertEquals((0).getId());
}
JPA Predicate查询排序
对已删除数据和locationInfoId对数据进⾏过滤,然后根据deliveryType,orderPaytime字段对数据进⾏排序,前三种deliveryType的订单排在前⾯,并按orderPaytime进⾏升序排列,后两种类型的订单排在后⾯,也按orderPaytime进⾏升序排列。
// 排除逻辑删除数据
predicates.add(criteriaBuilder.("dataStatus"), AuditModel.DATA_STATUS_ACTVIE));
if(null!= locationInfoId){
predicates.add(criteriaBuilder.("locationInfoId"), locationInfoId));
}
if(!StringUtils.isEmpty(shipStatus)){
CriteriaBuilder.In<Object> in = criteriaBuilder.("orderLatestStatus"));
String[] shipStatusArray = StringUtils.split(shipStatus,',');
Arrays.stream(shipStatusArray).forEach(x ->{
in.value(Integer.valueOf(x));
});
predicates.add(in);
}
criteriaQuery.Array(new Predicate[predicates.size()]));
//先根据 deliveryType 权重升序排
criteriaBuilder.asc(
criteriaBuilder.selectCase()
.when(criteriaBuilder.equal(
<("deliveryType"),"Home delivery 2h"),1)
.when(criteriaBuilder.equal(
<("deliveryType"),"C&C 2h"),1)
.when(criteriaBuilder.equal(
<("deliveryType"),"tmalldss"),1)
.when(criteriaBuilder.equal(
<("deliveryType"),"Home delivery"),3)
.when(criteriaBuilder.equal(
<("deliveryType"),"C&C"),3)
.otherwise(99)),
//再根据 orderPaytime 升序排
criteriaBuilder.("orderPaytime"))
);
Restriction();
};
like做模糊匹配,gt筛选⼤于填⼊参数的数据,lt筛选⼩于输⼊参数的数据
Specification<ShipOrderInfo> spec =new Specification<ShipOrderInfo>(){
public Predicate toPredicate(Root<ShipOrderInfo> root,
CriteriaQuery<?> query, CriteriaBuilder cb){
Predicate p1 = cb.("name").as(String.class),"%"+um.getName()+"%");
Predicate p2 = cb.("uuid").as(Integer.class), um.getUuid());
Predicate p3 = cb.("age").as(Integer.class), um.getAge());
//把Predicate应⽤到CriteriaQuery中去,因为还可以给CriteriaQuery添加其他的功能,⽐如排序、分组啥的 query.where(cb.and((p1,p2)));
//添加排序的功能
Restriction();
}
};
复杂⼀点的查询demo
// 排除逻辑删除数据
predicates.add(criteriaBuilder.("dataStatus"), AuditModel.DATA_STATUS_ACTVIE));
if(null!= locationInfoId){
predicates.add(criteriaBuilder.("locationInfoId"), locationInfoId));
}
if(!StringUtils.isEmpty(shipStatus)){
CriteriaBuilder.In<Object> in = criteriaBuilder.("orderLatestStatus"));
String[] shipStatusArray = StringUtils.split(shipStatus,',');
Arrays.stream(shipStatusArray).forEach(x ->{
in.value(Integer.valueOf(x));
});
jpa mybatispredicates.add(in);
}
criteriaQuery.Array(new Predicate[predicates.size()]));
//先根据 deliveryType 权重升序排
criteriaBuilder.asc(
criteriaBuilder.selectCase()
.when(criteriaBuilder.equal(
<("deliveryType"),"Home delivery 2h"),1)
.when(criteriaBuilder.equal(
<("deliveryType"),"C&C 2h"),1)
.when(criteriaBuilder.equal(
<("deliveryType"),"tmalldss"),1)
.when(criteriaBuilder.equal(
<("deliveryType"),"Home delivery"),3)
.when(criteriaBuilder.equal(
<("deliveryType"),"C&C"),3)
.otherwise(99)),
//再根据 orderPaytime 升序排
criteriaBuilder.("orderPaytime"))
);
Restriction();
};
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论