前言

继上次SpringData-JPA之ExampleMatcher实例查询使用一会之后发现ExampleMatcher对日期的查询特别糟糕,所以才有了Specification查询的研究。

  • 20200114:更新对JpaSpecificationExecutor的解析,Specification思路2,以及CriteriaBuilder +CriteriaQuery+Predicate+TypedQuery查询部分
  • 20180811:根据所学所用,重新更新了文章,并增加了Pageable分页排序功能。

实现

对应的Repository需要实现JpaSpecificationExecutor接口

public interface EventRepository extends JpaRepository<Event, Integer> , JpaSpecificationExecutor<Event>{

Specification与Controller业务逻辑

 @GetMapping("/event/list")public ApiReturnObject findAllEvent(String eventTitle,Timestamp registerTime,Integer pageNumber,Integer pageSize) {if(pageNumber==null) pageNumber=1;if(pageSize==null) pageNumber=10;//分页//Pageable是接口,PageRequest是接口实现,new PageRequest()是旧方法,PageRequest.of()是新方法//PageRequest.of的对象构造函数有多个,page是页数,初始值是0,size是查询结果的条数,后两个参数参考Sort对象的构造方法Pageable pageable = PageRequest.of(pageNumber,pageSize,Sort.Direction.DESC,"id");//Specification查询构造器Specification<Event> specification=new Specification<Event>() {private static final long serialVersionUID = 1L;@Overridepublic Predicate toPredicate(Root<Event> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {Predicate condition1 = null;if(StringUtils.isNotBlank(eventTitle)) {condition1 = criteriaBuilder.like(root.get("eventTitle"),"%"+eventTitle+"%");}else {condition1 = criteriaBuilder.like(root.get("eventTitle"),"%%");}Predicate condition2 = null;if(registerTime!=null) {condition2 = criteriaBuilder.greaterThan(root.get("registerTime"), registerTime);}else {condition2 = criteriaBuilder.greaterThan(root.get("registerTime"), new Timestamp(1514736000000L));}//Predicate conditionX=criteriaBuilder.and(condition1,condition2);//query.where(conditionX);query.where(condition1,condition2);//query.where(getPredicates(condition1,condition2)); //这里可以设置任意条查询条件return null;  //这种方式使用JPA的API设置了查询条件,所以不需要再返回查询条件Predicate给Spring Data Jpa,故最后return null}};Page<Event> list=eventRepository.findAll(specification, pageable);return ApiReturnUtil.page(list);}

ApiReturnUtil.page封装

其实这个大家根据自己的项目自己封装,这部分不作为核心内容,知识之前有部分网友比较纠结这个工具,所以简单放出来参考一下.

 public static ApiReturnObject page(Page returnObject) {return new ApiReturnObject(returnObject.getNumber()+"",returnObject.getNumberOfElements()+"",returnObject.getTotalElements()+"",returnObject.getTotalPages()+"","00","success",returnObject.getContent());   }

ApiReturnObject的主要内容:

 String errorCode="00";Object errorMessage;Object returnObject;String pageNumber;String pageSize;String totalElements;String totalPages;public ApiReturnObject(String pageNumber,String pageSize,String totalElements,String totalPages,String errorCode, Object errorMessage, Object returnObject) {super();this.pageNumber = pageNumber;this.errorCode = errorCode;this.errorMessage = errorMessage;this.returnObject = returnObject;this.pageSize = pageSize;this.totalElements = totalElements;this.totalPages = totalPages;}

查询效果

返回对象有用的是pageNumber、pageSize、totalElements、totalPages等属性,可对其进行封装

{"errorCode": "00","errorMessage": "success","pageNumber": "1","pageSize": "2","returnObject": [{"eventTitle": "1111","id": 3,"registerTime": 1528702813000,"status": "0"},{"eventTitle": "小明失踪","id": 2,"registerTime": 1526268436000,"status": "0"}],"totalElements": "5","totalPages": "3"
}

可以查询了。网上关于这个的资料也很少。希望可以帮到大家。

可能遇到的错误

Unable to locate Attribute  with the the given name [event] on this ManagedType [org.microservice.tcbj.yytsg.checkcentersys.entity.Event]

出现这样的情况,一般是因为实体类中没有这个属性,例如我Event的是eventTitle,写成了event,就会报错。

JpaSpecificationExecutor接口

20200114补充
JPA 提供动态接口JpaSpecificationExecutor,利用类型检查的方式,利用Specification进行复杂的条件查询,比自己写 SQL 更加便捷和安全.

public interface JpaSpecificationExecutor<T> {/*** Returns a single entity matching the given {@link Specification}.* * @param spec* @return*/T findOne(Specification<T> spec);/*** Returns all entities matching the given {@link Specification}.* * @param spec* @return*/List<T> findAll(Specification<T> spec);/*** Returns a {@link Page} of entities matching the given {@link Specification}.* * @param spec* @param pageable* @return*/Page<T> findAll(Specification<T> spec, Pageable pageable);/*** Returns all entities matching the given {@link Specification} and {@link Sort}.* * @param spec* @param sort* @return*/List<T> findAll(Specification<T> spec, Sort sort);/*** Returns the number of instances that the given {@link Specification} will return.* * @param spec the {@link Specification} to count instances for* @return the number of instances*/long count(Specification<T> spec);
}

Specification

Specification是我们传入进去的查询参数,是一个接口,并且只有一个方法

public interface Specification<T> {Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}

一个一目了然的方法

第二个实现思路,听说这个方法已经过时了,其实这个方法是最好理解的.这里附上作为思路参考.

public Page<Even> findAll(SearchEven even) {Specification<Even> specification = new Specifications<Even>().eq(StringUtils.isNotBlank(even.getId()), "id", even.getId()).gt(Objects.nonNull(even.getStatus()), "status", 0).between("registerTime", new Range<>(new Date()-1, new Date())).like("eventTitle", "%"+even.getEventTitle+"%").build();return personRepository.findAll(specification, new PageRequest(0, 15));
}

Criteria+TypedQuery

思路三,利用EntityManager相关的CriteriaBuilder +CriteriaQuery+Predicate+TypedQuery进行查询.

@PersistenceContext
private EntityManager em;/*** CriteriaBuilder 安全查询创建工厂,创建CriteriaQuery,创建查询具体具体条件Predicate* @author zhengkai.blog.csdn.net*/
@Override
public List<Even> list(Even even) {//查询工厂CriteriaBuilder cb = em.getCriteriaBuilder();//查询类CriteriaQuery<Even> query = cb.createQuery(Even.class);//查询条件List<Predicate> predicates = new LinkedList<>();//查询条件设置predicates.add(cb.equal("id", even.getId()));predicates.add(cb.like("eventTitle", even.getEventTitle()));//拼接where查询query.where(cb.or(predicates.toArray(new Predicate[predicates.size()])));//用JPA 2.0的TypedQuery进行查询TypedQuery<Even> typedQuery = em.createQuery(query);return typedQuery.getResultList();
}

SpringDataJPA之Specification复杂查询相关推荐

  1. jpa Specification fetch查询报错,query specified join fetching, but the owner of the fetched association

    jpa Specification fetch查询报错,query specified join fetching, but the owner of the fetched association ...

  2. SpringBoot使用SpringDataJPA通过方法名查询

    文章目录 JPA方法名查询 1. 方法名表图 2. 举例说明 3. 测试 JPA依赖及配置在这篇文章: SpringBoot框架使用SpringDataJPA JPA方法名查询 约定方法名一定要根据命 ...

  3. Spring之Specification复杂查询和Criteria查询

    Specification官网 [一目了然]Spring Data JPA使用Specification动态构建多表查询.复杂查询及排序示例 JPA 使用 Specification 复杂查询和 Cr ...

  4. spring-data-jpa specification 复杂查询之 zuji-jpa

    Zuji-JPA 官方文档 Zuji-JPA 是一个不用写sql的 Spring Data JPA 增强库,在 Spring Data JPA 的基础上简化开发,目的是让开发者不再去书写冗长的SQL, ...

  5. 使用jap的specification动态查询的演示案例与一些注意事项

    目录 学习背景与使用步骤 使用specification进行动态分页查询案例演示,包含按时间的范围查询 学习背景与使用步骤 最近在项目中遇到一个需求:对单个或者是多个条件进行分页查询(写在一个接口中) ...

  6. SpringDataJPA多表联合查询

    相信大家都用过jpa,jpa继承CrudRepository和PagingAndSortingRepository接口之后,在简单的单表查询中,不管是使用自带的findAll(),saveAll等方法 ...

  7. springDataJpa实现普通模糊查询

    1.需求 2.页面代码 <input type="text" id="id_keywords" class="form-control" ...

  8. Spring-data-jpa最全的查询语法总结,直入超神

  9. SpringBoot使用SpringDataJPA通过@Query注解多对多分页查询

    文章目录 SpringBoot使用JPA@Query注解查询 1. 环境配置 2. 数据库表配置 3. 实体类配置 4. Dao代码 5. Service 代码 6. Controller 代码 7. ...

  10. spring data jpa封装specification实现简单风格的动态查询

    github:https://github.com/peterowang/spring-data-jpa-demo 单一实体的动态查询: @Servicepublic class AdvancedUs ...

最新文章

  1. Android Studio打包生成APK
  2. 用户体验思考之UI面试
  3. 构建虚拟主机以及访问控制
  4. 大数据技术:Zookeeper分布式协调服务
  5. 把执行结果转成json对象报错_JSONObject获取值后为一个对象,将对象转为JSONObject时报错...
  6. go 关闭通道的必要性
  7. 【JQuery】JQuery学习笔记
  8. python的print函数输出带颜色字体
  9. http :请求响应报文-web服务-ajax-cors跨域
  10. ubuntu 16.04 python3.4 升级为 python3.6
  11. JavaWeb——关于RequestDispatcher的原理
  12. android二维码工程之仿QQ二维码实现
  13. sudo gem install cocoapods
  14. SVN安装和中文语言包安装
  15. AI产品经理的技术了解层级
  16. Windows cmd常用命令
  17. python中set什么意思_python中set详解
  18. 9. Enhancing Aspect Term Extraction with Soft Prototypes论文阅读笔记
  19. 不只Keep、FITURE、乐刻,运动健身赛道近5年吸金633亿早已起飞
  20. 程序员如何提高编程时打字速度的5个Tips

热门文章

  1. OSChina 周一乱弹 —— 最萌碰瓷
  2. 只有一条线的生存分析图 复杂一点的生存分析 及其参数详细解释
  3. 知网计算机论文查重查代码,知网查重会查代码么?
  4. C++基础笔记——汇总版(上)
  5. ubuntu中文论坛
  6. 力扣刷题思考:347. 前 K 个高频元素
  7. 数据结构与算法——栈( Stack )
  8. Java工程师 数据结构与算法 数组面试题(Day40)
  9. Microsoft Designer 微软设计师 拆机(拆鼠标)路程
  10. ADSL上网全攻略——故障解决