spring-data-jpa动态查询

60 阅读1分钟

一. 重要的两个接口

1.Specification接口

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.data.jpa.domain;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import java.io.Serializable;
import java.util.Arrays;
import java.util.stream.StreamSupport;
import org.springframework.lang.Nullable;

public interface Specification<T> extends Serializable {
 long serialVersionUID = 1L;

 static <T> Specification<T> not(@Nullable Specification<T> spec) {
     return spec == null ? (root, query, builder) -> {
         return null;
     } : (root, query, builder) -> {
         return builder.not(spec.toPredicate(root, query, builder));
     };
 }

 static <T> Specification<T> where(@Nullable Specification<T> spec) {
     return spec == null ? (root, query, builder) -> {
         return null;
     } : spec;
 }

 default Specification<T> and(@Nullable Specification<T> other) {
     return SpecificationComposition.composed(this, other, CriteriaBuilder::and);
 }

 default Specification<T> or(@Nullable Specification<T> other) {
     return SpecificationComposition.composed(this, other, CriteriaBuilder::or);
 }

 @Nullable
 Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);

 static <T> Specification<T> allOf(Iterable<Specification<T>> specifications) {
     return (Specification)StreamSupport.stream(specifications.spliterator(), false).reduce(where((Specification)null), Specification::and);
 }

 @SafeVarargs
 static <T> Specification<T> allOf(Specification<T>... specifications) {
     return allOf((Iterable)Arrays.asList(specifications));
 }

 static <T> Specification<T> anyOf(Iterable<Specification<T>> specifications) {
     return (Specification)StreamSupport.stream(specifications.spliterator(), false).reduce(where((Specification)null), Specification::or);
 }

 @SafeVarargs
 static <T> Specification<T> anyOf(Specification<T>... specifications) {
     return anyOf((Iterable)Arrays.asList(specifications));
 }
}
  1. toPredicate方法
    • Root root:代表查询的根对象,通常是一个实体。通过root,你可以获取到实体中的属性,用于构建查询条件。
    • CriteriaQuery<?> query:代表一个特定的查询,可以从中得到查询的结果类型等信息。
    • CriteriaBuilder criteriaBuilder:用于构建Predicate实例,这是查询条件的主要构建器。
  2. not方法(解析的例子,其他方法类似)
    • @Nullable表示入参可以为空。
    • (root,query,builder) -> null是一个lambda表达式,直接返回一个返回值为null的查询条件。

2. JpsSpecificationExecutor接口

  • 接口中的方法均接收一个Specification类型参数
  • 我们自己的Repository通过继承psSpecificationExecutor接口便可调用这些方法

二. 编写代码

  1. 定义Entity
  2. 定义Repository
  3. 实现方法
public Goods queryOne() {
    Optional<Goods> one = goodsRepository.findOne(new Specification<Goods>() {
        @Override
        public Predicate toPredicate(Root<Goods> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
            // ... 自定义逻辑
            return null;
        }
    });
    return one.get();
}