在优锐课的学习分享中探讨了关于,Spring Data JPA的创建主要是为了通过按方法名称生成查询来轻松创建查询。 但是,有时我们需要创建复杂的查询,而无法利用查询生成器。码了很多知识笔记分享给大家。

Spring Data JPA提供了一个存储库编程模型,该模型以每个受管域对象的接口开头。 定义这些接口有两个目的:首先,通过扩展JpaRepository,我们获得了一堆通用的CRUD方法,例如save,findAll,delete等。 其次,这将允许Spring Data JPA存储库基础结构扫描该接口的类路径并为其创建Spring Bean。 典型的存储库界面如下所示:

 public interface CustomerRepository extends JpaRepository<Customer, Long> {

   Customer findByEmailAddress(String emailAddress);

   List<Customer> findByLastname(String lastname, Sort sort);

   Page<Customer> findByFirstname(String firstname, Pageable pageable);

 }

要创建复杂的查询,为什么要指定规格?

是的,可以使用Criteria API构建复杂的查询。 要了解为什么要使用规范,我们考虑一个简单的业务需求。 我们将使用Criteria API以及随后的规范来实现此要求。

这是用例:在客户生日那天,我们希望向所有长期客户发送优惠券。 我们如何检索一个匹配的?

我们有两个谓词:

 LocalDate today = new LocalDate();

 CriteriaBuilder builder = em.getCriteriaBuilder();

 CriteriaQuery<Customer> query = builder.createQuery(Customer.class);

 Root<Customer> root = query.from(Customer.class);

 Predicate hasBirthday = builder.equal(root.get(Customer_.birthday), today);

 Predicate isLongTermCustomer = builder.lessThan(root.get(Customer_.createdAt), today.minusYears(2);

 query.where(builder.and(hasBirthday, isLongTermCustomer));

 em.createQuery(query.select(root)).getResultList();

在上面的代码中,

  • ·第一行创建了LocalDate以比较客户的生日和今天的日期。
  • ·以下三行包含用于设置必要的JPA基础结构实例的样板代码。
  • ·然后,在接下来的两行中,我们将构建谓词
  • ·在最后两行中,一个用于连接两个谓词,最后一个用于执行查询。

此代码的主要问题在于谓词不易于外部化和重用,因为您需要先设置CriteriaBuilder,CriteriaQuery和Root。 另外,由于难以快速推断出代码的意图,因此代码的可读性很差。

规格

为了能够定义可重用谓词,我们引入了规范接口,该接口源自Eric Evans的《域驱动设计》一书中引入的概念。 它将规范定义为实体的谓词,这正是规范接口所代表的含义。 实际上,这仅包含一个方法:

 public interface Specification<T> {

   Predicate toPredicate(Root<T> root, CriteriaQuery query, CriteriaBuilder cb);

 }

使用Java 8时,代码变得非常清晰易懂。

 public CustomerSpecifications {

   public static Specification<Customer> customerHasBirthday() {

 return (root, query, cb) ->{

 return cb.equal(root.get(Customer_.birthday), today);

 };

  }

  public static Specification<Customer> isLongTermCustomer() {

 return (root, query, cb) ->{

         return cb.lessThan(root.get(Customer_.createdAt), new LocalDate.minusYears(2));

 };

 }

 }

客户端现在可以执行以下操作:

 customerRepository.findAll(hasBirthday());

 customerRepository.findAll(isLongTermCustomer());

在这里,基本实现将为您准备CriteriaQuery,Root和CriteriaBuilder,应用由给定规范创建的谓词并执行查询。

我们只是创建了可以单独执行的可重用谓词。 我们可以结合使用这些单独的谓词来满足我们的业务需求。 我们有一个帮助程序类规范,它提供了(和)和(或)方法来连接原子规范。

 customerRepository.findAll(where(customerHasBirthday()).and(isLongTermCustomer()));

与仅使用JPA Criteria API相比,它读起来很流利,提高了可读性并提供了更多的灵活性。 这里唯一需要说明的是,提出规范实现需要相当多的编码工作。

以下是规范的一些优点:

  1. 所有“基本”查询都已实现,即findById,保存和删除
  2. 分页功能开箱即用。 您可以简单地将一个可分页对象从Controller传递到Service到您的存储库,并且可以正常工作(甚至可以排序)!
  3. 使用Spring的Specification API比普通的JPA简单一些,因为您只需创建谓词,而不必弄乱EntityManager和PersistenceContext。

如果您有任何要添加或共享的内容,请在下面的评论部分中留言。

祝大家学习愉快!

正确使用Spring Data JPA规范的更多相关文章

  1. Spring Data Jpa 规范接口表

      Keyword Sample JPQL snippet And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname ...

  2. spring data jpa(一)

    第1章     Spring Data JPA的快速入门 1.1   需求说明 Spring Data JPA完成客户的基本CRUD操作 1.2   搭建Spring Data JPA的开发环境 1. ...

  3. 12 Spring Data JPA:springDataJpa的运行原理以及基本操作(上)

    spring data jpaday1:orm思想和hibernate以及jpa的概述和jpa的基本操作 day2:springdatajpa的运行原理 day2:springdatajpa的基本操作 ...

  4. 16 搭建Spring Data JPA的开发环境

    使用Spring Data JPA,需要整合Spring与Spring Data JPA,并且需要提供JPA的服务提供者hibernate,所以需要导入spring相关坐标,hibernate坐标,数 ...

  5. Spring Data JPA 整合Spring

    1.1   Spring Data JPA 与 JPA和hibernate之间的关系 JPA是一套规范,内部是有接口和抽象类组成的.hibernate是一套成熟的ORM框架,而且Hibernate实现 ...

  6. Spring Data JPA方法定义规范

    Spring Data Jpa方法定义的规则: (1)简单条件查询 简单条件查询:查询某一个实体类或者集合. 按照Spring Data的规范的规定,查询方法以find | read | get开头, ...

  7. 74. Spring Data JPA方法定义规范【从零开始学Spring Boot】

    [从零开始学习Spirng Boot-常见异常汇总] 事情的起因:有人问过我们这个这个问题:为什么我利用Spring data jpa写的方法没有按照我想要的情况进行执行呢?我记得当时只是告诉他你你先 ...

  8. 深入浅出学Spring Data JPA

    第一章:Spring Data JPA入门 Spring Data是什么 Spring Data是一个用于简化数据库访问,并支持云服务的开源框架.其主要目标是使得对数据的访问变得方便快捷,并支持map ...

  9. 干货|一文读懂 Spring Data Jpa!

    有很多读者留言希望松哥能好好聊聊 Spring Data Jpa!其实这个话题松哥以前零零散散的介绍过,在我的书里也有介绍过,但是在公众号中还没和大伙聊过,因此本文就和大家来仔细聊聊 Spring D ...

随机推荐

  1. Virtual Box复制虚拟机

    用惯了VM换BOX还是有点不大一样的,比如复制 我用了2个网卡,所以看起来麻烦了一次 注释了UUID 应该有更好的办法来操作,下面的看起来有点啰嗦,先凑合着这样弄... 1.关机 2.复制 3.改名称 ...

  2. Ubuntu上安装python模块

    sudo apt-get install python-pip   ----先安装 pip模块 sudo pip install openpyxl ---通过pip安装python模块

  3. 删除文件linux

    bool LxDeleteFile(const char* src){ int32_t iRe = remove(src); ) return true; else return false; }

  4. RabbitMQ几个常用面试题

    以下观点,仅为个人理解的总结,如有错漏,欢迎指正! -------------------------------------------------------------------------- ...

  5. Springcloud 配置 | 史上最全,一文全懂

    Springcloud 高并发 配置 (一文全懂) 疯狂创客圈 Java 高并发[ 亿级流量聊天室实战]实战系列之15 [博客园总入口 ] 前言 疯狂创客圈(笔者尼恩创建的高并发研习社群)Spring ...

  6. MySQL 在 Windows 下安装教程、避坑指南

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,2008 年被 SUN 公司收购,后 SUN 公司又被 Oracle 公司收购. 一.下载 MySQL 官网 https:/ ...

  7. Spring Cloud(一):入门篇

    Spring Cloud 简介 Spring Cloud 是一个基于 Spring Boot 实现的微服务架构开发工具,可以快速构建分布式系统中的某些常用模式,如配置管理.服务治理.断路器.智能路由. ...

  8. 更改组织属性-以更改maxrecordsforexporttoexcel为例

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复232或者20161101可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  9. 【JDBC】CRUD操作

    JDBC的CRUD操作 向数据库中保存记录 修改数据库中的记录 删除数据库中的记录 查询数据库中的记录 保存代码的实现 package demo1; import java.sql.Connectio ...

  10. SQL Server通过函数把逗号分隔的字符串拆分成数据列表的脚本-干货

    CREATE FUNCTION [dbo].[Split](@separator VARCHAR(64)=',',@string NVARCHAR(MAX))  RETURNS @ResultTab ...