目录

持久化 API 接口概述

JpaSpecificationExecutor 常用 API

JPA Specification 编码示例


持久化 API 接口概述

1、JPA 持久化 API 接口主要如下:

public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> 
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> 
public interface JpaRepositoryImplementation<T, ID> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> 
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID>

2、JpaRepository 接口拥有常用的 CURD 方法以及分页方法、字段排序等操作,但是没有与或非、like、以及大于等于、小于等于等操作,这些方法都在 JpaSpecificationExecutor 接口中。

3、如果只需要简单的实现 CRUD、分页、排序,则继承 JpaRepository接口即可,如果还需要复杂查询,则可以再继承 JpaSpecificationExecutor 接口。当然也可以直接继承 JpaRepositoryImplementation 接口。

JpaSpecificationExecutor 常用 API

org.springframework.data.jpa.repository.JpaSpecificationExecutor
List<T> findAll(@Nullable Specification<T> spec) 规范查询。没有数据时返回空列表。
Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable) 规范查询。同时进行分页查询。
List<T> findAll(@Nullable Specification<T> spec, Sort sort) 规范查询。同时指定排序字段。
Optional<T> findOne(@Nullable Specification<T> spec) 规范查询单条数据。注意如果结果多余一条,则抛异常。

JPA Specification 编码示例

1、本文承接《《Spring Data JPA 常用 CRUD 操作汇总》,环境为 Spring boot 2.1.4。下面列举几项稍微说明,实际中对于其它需求,同理可以参看 jpa 源码进行编写即可。

持久化层

import com.wmx.entity.TV;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/*** Java 接口可以多继承* JpaRepository 中有常用的 CRUD 、分页、排序等方法* JpaSpecificationExecutor 可以实现任意的复杂查询*/
public interface TVRepository extends JpaRepository<TV, Integer>, JpaSpecificationExecutor<TV> {
}

service 业务层

在线源码:https://github.com/wangmaoxiong/h2Smil/blob/master/src/main/java/com/wmx/service/TvService.java

在线源码:https://github.com/wangmaoxiong/h2Smil/blob/master/src/main/java/com/wmx/service/impl/TvServiceImpl.java

public interface TVService {//条件查询时间范围在 [start,end] 之间的数据。如果 tvName 不为空,加上名称条件List<TV> findAll(Date start, Date end, String tvName);//查询生产日期大于等于 start 的数据,且进行分页查询Page<TV> findAll(Date start, int page, int size);//模糊查询 likeList<TV> findAllLike(String tvNameLike);
}
@Service
public class TVServiceImpl implements TVService {@Resourceprivate TVRepository tvRepository;@Overridepublic List<TV> findAll(Date start, Date end, String tvName) {//直接使用匿名内部类实现接口Specification specification = new Specification<TV>() {@Overridepublic Predicate toPredicate(Root<TV> root, CriteriaQuery<?> query, CriteriaBuilder cb) {List<Predicate> predicateList = new ArrayList<>();//条件1:查询 tvName 为 海信 的数据,root.get 中的值与 TV 实体中的属性名称对应if (tvName != null && !"".equals(tvName)) {predicateList.add(cb.equal(root.get("tvName").as(String.class), tvName));}//条件2:TV 生产日期(dateOfProduction)大于等于 start 的数据,root.get 中的 dateOfProduction 必须对应 TV 中的属性predicateList.add(cb.greaterThanOrEqualTo(root.get("dateOfProduction").as(Date.class), start));//条件3:TV 生产日期(dateOfProduction)小于等于 endpredicateList.add(cb.lessThanOrEqualTo(root.get("dateOfProduction").as(Date.class), end));Predicate[] pre = new Predicate[predicateList.size()];pre = predicateList.toArray(pre);return query.where(pre).getRestriction();}};return tvRepository.findAll(specification);//没有数据时,返回空列表}@Overridepublic Page<TV> findAll(Date start, int page, int size) {page--;page = page < 0 ? 0 : page;//page 为页码,数据库从0页开始//可以使用重载的 of(int page, int size, Sort sort) 方法指定排序字段Pageable pageable = PageRequest.of(page, size);//创建查询规范Specification<TV> tvSpecification = new Specification<TV>() {@Overridepublic Predicate toPredicate(Root<TV> root, CriteriaQuery<?> query, CriteriaBuilder cb) {List<Predicate> predicateList = new ArrayList<>();//查询生产日期在 start 与当期时间之间的数据,闭区间predicateList.add(cb.between(root.get("dateOfProduction").as(Date.class), start, new Date()));Predicate[] predicates = new Predicate[predicateList.size()];return query.where(predicateList.toArray(predicates)).getRestriction();}};return tvRepository.findAll(tvSpecification, pageable);//无数据时返回空列表}@Overridepublic List<TV> findAllLike(String tvNameLike) {Specification<TV> tvSpecification = new Specification<TV>() {@Overridepublic Predicate toPredicate(Root<TV> root, CriteriaQuery<?> query, CriteriaBuilder cb) {Predicate[] predicates = new Predicate[1];//like(Expression<String> x, String pattern):参数 pattern 表示匹配的格式predicates[0] = cb.like(root.get("tvName").as(String.class), "%" + tvNameLike + "%");//同理以 xxx 开头,则为 tvNameLike + "%"return query.where(predicates).getRestriction();}};//规范查询的同时,指定以主键 tvId 倒序排序return tvRepository.findAll(tvSpecification, Sort.by(Sort.Direction.DESC, "tvId"));}
}

控制器层

在线源码: https://github.com/wangmaoxiong/h2Smil/blob/master/src/main/java/com/wmx/controller/TvController.java

@Controller
public class TVController {@Resourceprivate TVService tvService;@GetMapping("findAll1")@ResponseBodypublic String findAll1(String name) throws ParseException {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date start = dateFormat.parse("2019-04-27 10:00:00");Date end = dateFormat.parse("2019-04-27 23:00:00");return tvService.findAll(start, end, name).toString();}@GetMapping("findAll2")@ResponseBodypublic String findAll2(Integer page, Integer size) throws ParseException {page = page == null ? 1 : page;size = size == null ? 2 : size;SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date start = dateFormat.parse("2019-04-28 08:00:00");Page<TV> tvPage = tvService.findAll(start, page, size);Logger logger = Logger.getAnonymousLogger();logger.info("总记录数:" + tvPage.getTotalElements());logger.info("总页数:" + tvPage.getTotalPages());List<TV> tvList = tvPage.getContent();return tvList.toString();}@GetMapping("findAll3")@ResponseBodypublic String findAll3(String like) throws ParseException {return tvService.findAllLike(like).toString();}
}

github 地址:https://github.com/wangmaoxiong/h2Smil

Spring Data JPA Specification(规范)实现复杂查询相关推荐

  1. Spring Data JPA Specification多表关联查询

    需求:有一个流量计的设备,流量计有一个所属罐区id,想要通过所属罐区查到所关联的这个罐区的编码以及名称. 1.流量计实体类: 主要是给流量计实体添加了以下属性,通过tank_area_id关联: pa ...

  2. Spring Data JPA 实现多表关联查询

    原文链接:https://blog.csdn.net/johnf_nash/article/details/80587204 多表查询在spring data jpa中有两种实现方式,第一种是利用hi ...

  3. 【Spring Data JPA自学笔记三】Spring Data JPA的基础和高级查询方法

    文章目录 调用接口的基础方法查询 Repository CrudRepository PagingAndSortingRepository JPARepository JpaSpecification ...

  4. Spring Data JPA 从入门到精通~查询结果的处理

    参数选择(Sort/Pageable)分页和排序 特定类型的参数,Pageable 并动态 Sort 地将分页和排序应用于查询 案例:在查询方法中使用 Pageable.Slice 和 Sort. P ...

  5. Spring Data JPA 多条件判空查询

    Spring Data JPA虽然大大的简化了持久层的开发,但是在实际开发中,很多地方都需要高级动态查询. 使用@Query注解,这种方式可以直接在Repository里面写sql,但是这种方式的问题 ...

  6. Spring Data Jpa多表联合分页查询

    参考:https://blog.csdn.net/qq_36144258/article/details/80298354 近期一个项目用到Spring Data Jpa,Jpa用来做单表查询非常的简 ...

  7. Spring data jpa命名规范

    JPA命名规范 (sample与JPQL等效) Table 4. Supported keywords inside method names Keyword Sample JPQL snippet ...

  8. Spring data jpa Specification查询关于日期的范围搜索

    代码: 时间格式化类型: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat s ...

  9. Spring Data JPA 从入门到精通~查询方法的创建

    查询方法的创建 内部基础架构中有个根据方法名的查询生成器机制,对于在存储库的实体上构建约束查询很有用,该机制方法的前缀 find-By.read-By.query-By.count-By 和 get- ...

最新文章

  1. 2018.11.06-知识回顾
  2. ml--分类与预测算法评价方法
  3. python做啥用-你都用 Python 来做什么?
  4. Java反射之内部类
  5. C++——C++11中的defalut和delete关键字
  6. SAP License:SAP合同类型的使用
  7. monitor的用法Linux,usb monitor使用方法
  8. 佳明、杜斯曼集团等巨头遭勒索攻击;Emotet利用新技术实施攻击
  9. java linux driver,JAVA:使用GeckoDriver在Linux上运行Selenium测试:驱动程序不可执行
  10. (已更新)萤火商城V2.0开源版[uni-app端],轻量级前后端分离的电商系统,支持微信小程序 + H5+ 公众号 + APP
  11. 先进事迹计算机维护与维修,汽车维修工先进事迹
  12. C/C++项目:谁都爱玩的4399小游戏黄金矿工教程
  13. python布尔系列_python-布尔运算
  14. Android APP - GPS定位并获取地理位置
  15. php jsp显示数据排序,JSP_SQL数据库开发中的一些精典代码,1.按姓氏笔画排序: select * From T - phpStudy...
  16. Codeforces A. XXXXX (数学 / 双指针) (Round #649 Div.2)
  17. [Delphi]:解决3DMark闪退及3DMark宕的问题
  18. Spring中Bean及@Bean的理解
  19. Esri与欧盟委员会签订许可协议
  20. Jlink下载u-boot

热门文章

  1. “公私结合”打造完整会员营销体系
  2. PTA 黑洞数 C语言
  3. 怎样使div铺满整个屏幕
  4. IDEA快捷键汇总,很全,保证提高你的开发效率
  5. 交换机和猫、路由器到底有什么区别?
  6. Mongdb 删除重复数据python-pymongo实现
  7. 自然辩证法作业--科学与技术的关系
  8. k8s日志通过本地iTerm查看
  9. 机器学习_2逻辑回归
  10. 听java技术讲座心得体会_听讲座心得体会范文(精选3篇)