此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Data JPA 3.5.2spring-doc.cadn.net.cn

规格

JPA 2 引入了一个标准 API,您可以使用它以编程方式构建查询。通过编写一个criteria,则定义域类查询的 where 子句。再退一步,这些标准可以被视为 JPA 标准 API 约束所描述的实体的谓词。spring-doc.cadn.net.cn

Spring Data JPA 采用了 Eric Evans 的书“Domain Driven Design”中的规范概念,遵循相同的语义,并提供了一个 API 来使用 JPA 标准 API 定义此类规范。为了支持规范,您可以使用JpaSpecificationExecutor接口,如下所示:spring-doc.cadn.net.cn

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

附加接口具有允许您以多种方式运行规范的方法。例如,findAll方法返回与规范匹配的所有实体,如以下示例所示:spring-doc.cadn.net.cn

List<T> findAll(Specification<T> spec);

Specification接口定义如下:spring-doc.cadn.net.cn

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

规范可以很容易地用于在实体之上构建一组可扩展的谓词,然后可以将其组合并与JpaRepository无需为每个所需的组合声明查询(方法),如以下示例所示:spring-doc.cadn.net.cn

示例 1.客户规格
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_type 是使用 JPA Metamodel 生成器生成的元模型类型(有关示例,请参阅 Hibernate 实现的文档)。 所以表达式,Customer_.createdAt,假定Customer有一个createdAt属性Date. 除此之外,我们还在业务需求抽象级别表达了一些标准,并创建了可执行文件Specifications. 因此,客户端可能会使用Specification如下:spring-doc.cadn.net.cn

示例 2.使用简单的规范
List<Customer> customers = customerRepository.findAll(isLongTermCustomer());

为什么不为这种数据访问创建查询呢?使用单个Specification与普通查询声明相比,没有获得太多好处。当您将它们组合起来创造新的时,规范的力量才真正闪耀Specification对象。您可以通过默认方法实现此目的Specification我们提供类似于以下内容的构建表达式:spring-doc.cadn.net.cn

示例 3.组合规格
MonetaryAmount amount = new MonetaryAmount(200.0, Currencies.DOLLAR);
List<Customer> customers = customerRepository.findAll(
  isLongTermCustomer().or(hasSalesOfMoreThan(amount)));

Specification提供了一些“胶水代码”默认方法来链接和组合Specification实例。这些方法允许您通过创建新的Specification实现并将它们与现有实现相结合。spring-doc.cadn.net.cn

在 JPA 2.1 中,CriteriaBuilder引入 APICriteriaDelete.这是通过JpaSpecificationExecutor’s `delete(Specification)应用程序接口。spring-doc.cadn.net.cn

示例 4.使用Specification以删除条目。
Specification<User> ageLessThan18 = (root, query, cb) -> cb.lessThan(root.get("age").as(Integer.class), 18)

userRepository.delete(ageLessThan18);

Specification构建一个条件,其中age字段(转换为整数)小于18. 传递给userRepository,它将使用 JPA 的CriteriaDelete功能生成正确的DELETE操作。 然后返回已删除的实体数。spring-doc.cadn.net.cn