写点什么

使用 Spring Data JPA 的 Specification 构建数据库查询

作者:Java高工P7
  • 2021 年 11 月 11 日
  • 本文字数:1119 字

    阅读完需:约 4 分钟

}


  • findByEmailAddress 生成的 SQL 是根据 email_address 字段查询 Customer 表的数据

  • findByLastname 根据 lastname 字段查询 Customer 表的数据

  • findByFirstname 根据 firstname 字段查询 Customer 表的数据


以上所有的查询都不用我们手写 SQL,查询生成器自动帮我们工作,对于开发人员来说只需要记住一些关键字,如:findBy、delete 等等。但是,有时我们需要创建复杂一点的查询,就无法利用查询生成器。可以使用本节介绍的 Specification 来完成。


笔者还是更愿意手写 SQL 来完成复杂查询,但是有的时候偶尔使用一下 Specification 来完成任务,也还是深得我心。不排斥、不盲从。没有最好的方法,只有最合适的方法!


一、使用 Criteria API 构建复杂的查询




是的,除了 specification,我们还可以使用 Criteria API 构建复杂的查询,但是没有 specification 好用。我们来看一下需求:在客户生日当天,我们希望向所有长期客户(2 年以上)发送优惠券。我们如何该检索 Customer?


我们有两个谓词查询条件:


  • 生日

  • 长期客户-2 年以上的客户。


下面是使用 JPA 2.0 Criteria API 的实现方式:


LocalDate toda


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


y = 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用于比较客户的生日和今天的日期。em 是 javax.persistence.EntityManager

  • 下三行包含用于查询 Customer 实体的 JPA 基础结构实例的样板代码。

  • 然后,在接下来的两行中,我们将构建谓词查询条件

  • 在最后两行中,where 用于连接两个谓词查询条件,最后一个用于执行查询。


此代码的主要问题在于,谓词查询条件不易于重用,您需要先设置?CriteriaBuilder, CriteriaQuery,和Root。另外,代码的可读性也很差。


二、specification




为了能够定义可重用谓词条件,我们引入了 Specification 接口。


public interface Specification<T> {


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


}


结合 Java 8 的 lambda 表达式使用 Specification 接口时,代码变得非常简单


public CustomerSpecifications {


//查询条件:生日为今天


public static Specification<Customer> customerHasBirthday() {


return (root, query, cb) ->{

用户头像

Java高工P7

关注

还未添加个人签名 2021.11.08 加入

还未添加个人简介

评论

发布
暂无评论
使用Spring Data JPA的Specification构建数据库查询