开发过程中JPA Specification的应用


Specification算是JPA里面比较灵活的查询规范了,方便实现复杂的查询方式。

为什么需要Specification

Spring-Data JPA 本身支持了比较简单的查询方式,也就是根据属性名成结合一些规范编写查询方法,例如,一个Customer对象有name属性,那么如果想要实现根据name来查询,只需要在接口文件中添加一个方法findByName(String name)即可实现。

public interface CustomerRepository extends JpaRepository<Customer, Long> {
   
  Customer findByName(String name);
  Customer findByEmailAddress(String emailAddress);
  List<Customer> findByLastname(String lastname, Sort sort);
  Page<Customer> findByFirstname(String firstname, Pageable pageable);
}

但是在许多情况下,会有比较复杂的查询,那么这个时候通过自动生成查询方法的方式就不再可行。

应用场景

为了实现复杂查询,JPA提供了Criteria接口,这个是一套标准接口,来看一个例子,在一个平台中,当一个老客户(注册以来两年)生日的时候,系统想要发送一个优惠券给该用户,那么传统使用 JPA 2.0 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();
  • 首先获得时间,去比较用户的注册时间
  • 接下来是获得JPA中查询使用的实例
  • 设置查询条件,首先判断今天是否为某个客户的生日,然后判断是否为老客户
  • 执行查询条件,获得满足条件的用户
    这里面的主要问题就是代码扩展性比较差,因为需要设置CriteriaBuilder, CriteriaQuery, Root,同时这部分的代码可读性比较差。

JPA Specification实现复杂查询

Specification为了实现可重用的断言,JPA 里面引入了一个Specification接口,接口的封装很简单,如下

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

在Java8中,我们可以非常方便地实现如上使用Criteria实现的效果

public CustomerSpecifications {
   
    public static Specification<Customer> customerHasBirthday() {
   
        return (root, query, cb) -> {
    
            return cb.equal(root.get(Customer_.birthday), today);
        };
    }

    
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值