编程修炼之hibernate JPA之动态查询:Specification与Example的使用

官网

概述

JPA从2开始引入了criteria的api来编程式构建查询,对于变化参数的jpa编写提供了非常大的便利。Specitication并不能在查询便利上有多少优势,但是在动态添加条件进行多维组合的场景有非常好的效果。

Specification

jpa的接口要继承JpaSpecificationExecutor

public interface CustomerRepository extends CrudRepository<Customer, Long>, JpaSpecificationExecutor {
 …
}

查询就可以使用

List<T> findAll(Specification<T> spec);
public class CustomerSpecs {


  public static Specification<Customer> isLongTermCustomer() {
    return (root, query, builder) -> {
      LocalDate date = LocalDate.now().minusYears(2);
      return builder.lessThan(root.get(Customer_.createdAt), date);
    };
  }

  public static Specification<Customer> hasSalesOfMoreThan(MonetaryAmount value) {
    return (root, query, builder) -> {
      // build query here
    };
  }
}

Customer_ 是JPA元模型。Customer_.createdAt表示Customer对象有createAt属性(Date类型)
进行查询组合:

MonetaryAmount amount = new MonetaryAmount(200.0, Currencies.DOLLAR);
List<Customer> customers = customerRepository.findAll(
  isLongTermCustomer().or(hasSalesOfMoreThan(amount)));

在Specification中,buider相当于进行条件判断的部分,root实际上相当于表,从表中挑选字段,添加条件,然后返回判断标准Specification,交给数据库去查询。

Example

(QBE)是一种用户界面友好的查询技术。 它允许动态创建查询,并且不需要编写包含字段名称的查询。 实际上,按示例查询不需要使用特定的数据库的查询语言来编写查询语句。
Example api的组成
Probe: 含有对应字段的实例对象。
ExampleMatcher:ExampleMatcher携带有关如何匹配特定字段的详细信息,相当于匹配条件。
Example:由Probe和ExampleMatcher组成,用于查询。
适用场景:
使用一组静态或动态约束来查询数据存储。
频繁重构域对象,而不必担心破坏现有查询。
独立于基础数据存储API进行工作。
按示例查询也有一些限制:
不支持嵌套或分组属性约束,例如firstname =?0或(firstname =?1和lastname =?2)。
仅支持字符串的开始/包含/结束/正则表达式匹配,以及其他属性类型的完全匹配。

同Specification类似,Example的使用需要Repository接口继承QueryByExampleExecutor

public interface QueryByExampleExecutor<T> {

  <S extends T> S findOne(Example<S> example);

  <S extends T> Iterable<S> findAll(Example<S> example);

  // … more functionality omitted.
}


Person person = new Person();                         
person.setFirstname("Dave");                          
Example<Person> example = Example.of(person);       

扩展:Example Matchers

对字段查询细粒度的控制是依靠Matcher来实现的。

如下的案例:

  • 创建对象
  • 对象赋值
  • 创建ExampleMatcher
  • 忽略 lastname属性路径
  • 忽略 lastname属性路径并包含空值
  • 忽略 lastname属性路径并包含空值并进行后缀字符串匹配
  • 创建Example,配置对象与ExampleMatcher
Person person = new Person();                          
person.setFirstname("Dave");                           

ExampleMatcher matcher = ExampleMatcher.matching()     
  .withIgnorePaths("lastname")                         
  .withIncludeNullValues()                             
  .withStringMatcherEnding();                          

Example<Person> example = Example.of(person, matcher);

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值