正确使用Spring Data JPA规范
在优锐课的学习分享中探讨了关于,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相比,它读起来很流利,提高了可读性并提供了更多的灵活性。 这里唯一需要说明的是,提出规范实现需要相当多的编码工作。
以下是规范的一些优点:
- 所有“基本”查询都已实现,即findById,保存和删除
- 分页功能开箱即用。 您可以简单地将一个可分页对象从Controller传递到Service到您的存储库,并且可以正常工作(甚至可以排序)!
- 使用Spring的Specification API比普通的JPA简单一些,因为您只需创建谓词,而不必弄乱EntityManager和PersistenceContext。
如果您有任何要添加或共享的内容,请在下面的评论部分中留言。
祝大家学习愉快!
正确使用Spring Data JPA规范的更多相关文章
- Spring Data Jpa 规范接口表
Keyword Sample JPQL snippet And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname ...
- spring data jpa(一)
第1章 Spring Data JPA的快速入门 1.1 需求说明 Spring Data JPA完成客户的基本CRUD操作 1.2 搭建Spring Data JPA的开发环境 1. ...
- 12 Spring Data JPA:springDataJpa的运行原理以及基本操作(上)
spring data jpaday1:orm思想和hibernate以及jpa的概述和jpa的基本操作 day2:springdatajpa的运行原理 day2:springdatajpa的基本操作 ...
- 16 搭建Spring Data JPA的开发环境
使用Spring Data JPA,需要整合Spring与Spring Data JPA,并且需要提供JPA的服务提供者hibernate,所以需要导入spring相关坐标,hibernate坐标,数 ...
- Spring Data JPA 整合Spring
1.1 Spring Data JPA 与 JPA和hibernate之间的关系 JPA是一套规范,内部是有接口和抽象类组成的.hibernate是一套成熟的ORM框架,而且Hibernate实现 ...
- Spring Data JPA方法定义规范
Spring Data Jpa方法定义的规则: (1)简单条件查询 简单条件查询:查询某一个实体类或者集合. 按照Spring Data的规范的规定,查询方法以find | read | get开头, ...
- 74. Spring Data JPA方法定义规范【从零开始学Spring Boot】
[从零开始学习Spirng Boot-常见异常汇总] 事情的起因:有人问过我们这个这个问题:为什么我利用Spring data jpa写的方法没有按照我想要的情况进行执行呢?我记得当时只是告诉他你你先 ...
- 深入浅出学Spring Data JPA
第一章:Spring Data JPA入门 Spring Data是什么 Spring Data是一个用于简化数据库访问,并支持云服务的开源框架.其主要目标是使得对数据的访问变得方便快捷,并支持map ...
- 干货|一文读懂 Spring Data Jpa!
有很多读者留言希望松哥能好好聊聊 Spring Data Jpa!其实这个话题松哥以前零零散散的介绍过,在我的书里也有介绍过,但是在公众号中还没和大伙聊过,因此本文就和大家来仔细聊聊 Spring D ...
随机推荐
- tp、tftp、nfs--服务器搭建
服务器 1. ftp服务器 1.1检查是否安装 vsftpd -version 1.2 安装 sudo apt-get install vsftpd 1.3卸载 sudo apt-get remove ...
- 算法之冒泡排序手写之js写法andjava写法
对于经典算法,你是否也遇到这样的情形:学时觉得很清楚,可过阵子就忘了? 本系列文章帮助你解决这个问题. 其实排序算法,仔细品读他的名字就见名知意了. 比如冒泡排序就很形象,遍历n次,每次循环相邻元素两 ...
- TCP/IP网络协议初识
目录 一.什么是协议? 二.什么是TCP/IP协议? 三.TCP/IP为什么这么多协议? 四.TCP/IP协议为什么分层? 五.TCP/IP协议如何入门? 六.TCP/IP 的分层: 七.各协议层打包 ...
- linux-认识vi vim
vi 编译器 Linux vi 命令非常强大,熟练地使用它可以高效的编辑代码,配置系统文件等 命令:vi [文件] vim [文件] vi 分为三种模式:命令模式.文字模式.末尾模式 -------- ...
- iconv转换
/////////////////////////////////////////////////////// #include <iconv.h> #include <stdlib ...
- python-参数化-(1)(手机号码)
一.生成手机号码,此处并没有写成类或者函数形式,上代码 import random #指定手机号码前三位格式,并随机返回一个区号,关于random参数化的相关部分自行了解type_mobile = [ ...
- tensorflow和pytorch教程
https://github.com/dragen1860/Deep-Learning-with-TensorFlow-book
- Java之多线程创建方式
多线程的由来 我们在之前,学习的程序在没有跳转语句的前提下,都是由上至下依次执行,那现在想要设计一个程序,边打游戏边听歌,怎么设计?要解决上述问题,咱们得使用多进程或者多线程来解决. 多线程的好处: ...
- Vue父子组件数据双向绑定,子组件可修改props
第一种,子组件通过监听父组件数据,子组件改变数据之后通知给父组件 原文链接:https://blog.csdn.net/m0_37728716/article/details/81776929 父组件 ...
- B站弹幕爬取 / jieba分词 - 全站第一的视频弹幕都在说什么?
前言 本次爬取的视频av号为75993929(11月21的b站榜首),讲的是关于动漫革命机,这是一部超魔幻现实主义动漫(滑稽),有兴趣的可以亲身去感受一下这部魔幻大作. 准备工作 B站弹幕的爬取的接口 ...