Spring data jpa的使用与详解(复杂动态查询及分页,排序)
一、使用Specification实现复杂查询
(1)什么是Specification
Specification是springDateJpa中的一个接口,他是用于当jpa的一些基本CRUD操作的扩展,可以把他理解成一个springjpa的复杂查询接口。其次我们需要了解Criteria查询,这是是一种类型安全和更面向对象的查询。而SpringDataJPA支持JPA2.0的Criteria查询,相应的接口是JpaSpecificationExecutor。
而JpaSpecificationExecutor这个接口基本是围绕着Specification接口来定义的,Specification接口中只定义了如下一个方法:
PredicatetoPredicate(Rootroot,CriteriaQuery>query,CriteriaBuildercb);
Criteria查询基本概念:
Criteria查询是以元模型的概念为基础的,元模型是为具体持久化单元的受管实体定义的,这些实体可以是实体类,嵌入类或者映射的父类。
CriteriaQuery接口:
代表一个specific的顶层查询对象,它包含着查询的各个部分,比如:select、from、where、groupby、orderby等注意:CriteriaQuery对象只对实体类型或嵌入式类型的Criteria查询起作用。
Root:
代表Criteria查询的根对象,Criteria查询的查询根定义了实体类型,能为将来导航获得想要的结果,它与SQL查询中的FROM子句类似。
Root实例是类型化的,且定义了查询的FROM子句中能够出现的类型。root代表查询的实体类,query可以从中得到root对象,告诉jpa查询哪一个实体类,还可以添加查询条件,还可以结合EntityManager对象得到最终查询的TypedQuery对象。
CriteriaBuilder接口:
用来构建CritiaQuery的构建器对象Predicate:一个简单或复杂的谓词类型,其实就相当于条件或者是条件组合。可通过EntityManager.getCriteriaBuilder而得。
二、使用Specification进行复杂的动态查询
maven的依赖继续使用上一章的就可以,这里修改一下实体类和controller层。
请求实体类:
@Data
publicclassAccountRequest{
//从第几页开始
privateIntegerpage;
//每一页查询多少
privateIntegerlimit;
privateStringid;
privateStringname;
privateStringpwd;
privateStringemail;
privateInteger[]types;
}
实体类:
@Data
@Entity
@Table(name="account")
@ToString
@EntityListeners(AuditingEntityListener.class)
publicclassAccount{
@Id
@GenericGenerator(name="idGenerator",strategy="uuid")
@GeneratedValue(generator="idGenerator")
privateStringid;
@Column(name="username",unique=true,nullable=false,length=64)
privateStringusername;
@Column(name="password",nullable=false,length=64)
privateStringpassword;
@Column(name="email",length=64)
privateStringemail;
@Column(name="type")
privateShorttype;
@CreatedDate
@Column(name="create_time",nullable=false)
privateLocalDateTimecreateTime;
}
Repository层:
publicinterfaceAccountRepositoryextendsJpaRepository,JpaSpecificationExecutor {}
controller层(还是直接略过service层)
@Autowired
privateAccountRepositoryrepository;
@PostMapping("/get")
publicListget(@RequestBodyAccountRequestrequest){
Specificationspecification=newSpecification(){
@Override
publicPredicatetoPredicate(Rootroot,CriteriaQuery>criteriaQuery,CriteriaBuilderbuilder){
//所有的断言及条件
Listpredicates=newArrayList<>();
//精确匹配idpwd
if(request.getId()!=null){
predicates.add(builder.equal(root.get("id"),request.getId()));
}
if(request.getPwd()!=null){
predicates.add(builder.equal(root.get("password"),request.getPwd()));
}
//模糊搜索name
if(request.getName()!=null&&!request.getName().equals("")){
predicates.add(builder.like(root.get("username"),"%"+request.getName()+"%"));
}
if(request.getEmail()!=null&&!request.getEmail().equals("")){
predicates.add(builder.like(root.get("email"),"%"+request.getEmail()+"%"));
}
//in范围查询
if(request.getTypes()!=null){
CriteriaBuilder.In
通过重写Specification的toPredicate的方法,这样一个复杂的动态sql查询就完成了,通过post请求直接就可以调用了。
三、分页及排序
@PostMapping("/page")
publicListgetPage(@RequestBodyAccountRequestrequest){
Specificationspecification=newSpecification(){
@Override
publicPredicatetoPredicate(Rootroot,CriteriaQuery>criteriaQuery,CriteriaBuildercriteriaBuilder){
Listpredicates=newArrayList<>();
//doanything
returncriteriaBuilder.and(predicates.toArray(newPredicate[predicates.size()]));
}
};
//表示通过createTime进行ASC排序
PageRequestpage=newPageRequest(request.getPage()-1,request.getLimit(),Sort.Direction.ASC,"createTime");
PagepageInfo=repository.findAll(specification,page);
returnpageInfo.getContent();
}
上面的代码是在经过复杂查询并进行分页与排序,通过PageRequest来构建分页排序的规则。传入起始页及每页的数量,还有排序的规则及以哪个属性排序。jpa中是以第0页开始的,所以传参的时候需要注意!
当然,如果你不需要进行复杂的查询也可以对数据进行分页及排序查询。
修改repository,使其继承PagingAndSortingRepository。
@Repository publicinterfaceAccountRepositoryextendsJpaRepository,JpaSpecificationExecutor ,PagingAndSortingRepository { Page findByAge(intage,Pageablepageable); }
使用时先创建pageable参数,然后传进去就可以了。
//显示第1页每页显示3条 PageRequestpr=newPageRequest(1,3); //根据年龄进行查询 Pagestus=accountPageRepository.findByAge(22,pr);
排序也是一样的,在repository中创建方法
ListfindByPwd(Stringpwd,Sortsort);
调用的时候传入sort对象
//设置排序方式为username降序 Listaccs=accountPageRepository.findByAge("123456",newSort(Sort.Direction.DESC,"username")); //设置排序以username和type进行升序 acc=accountPageRepository.findByAge("123456",newSort(Sort.Direction.ASC,"username","type")); //设置排序方式以name升序,以address降序 Sortsort=newSort(newSort.Order(Sort.Direction.ASC,"name"),newSort.Order(Sort.Direction.DESC,"type")); accs=accountPageRepository.findByAge("123456",sort);
到此这篇关于Springdatajpa的使用与详解(复杂动态查询及分页,排序)的文章就介绍到这了,更多相关Springdatajpa内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!