springboot JPA 基本查詢和Specification查詢

 

0 背景

   springboot JPA提供了查詢數據的接口,使用起來簡潔且強大。以下主要從基本查詢和Specification查詢(實現更復雜的查詢)兩方面展開。

1 基本查詢

   1.1  JpaRepository使用

           只需繼承JpaRepository接口,便可以使用基本的查詢,具體方法可自行查看。

@Repository
public interface AIRepository extends JpaRepository<AI, String>{
}

   1.2 提供的方法(部分)

    <S extends T> S save(S entity);	
    Optional<T> findById(ID id);
    long count();
    void deleteById(ID id);
    List<T> findAll();
    List<T> findAll(Sort sort);
    Page<T> findAll(Pageable pageable);

       除此之外,也可在自己定義的AIRepository接口中創建查詢

@Repository
public interface AIRepository extends JpaRepository<AI, String>{

    List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
    List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
    List<Person> findByLastnameOrderByFirstnameAsc(String lastname);

    //使用 Pageable, Slice 和 Sort來查詢
    Page<User> findByLastname(String lastname, Pageable pageable);

    Slice<User> findByLastname(String lastname, Pageable pageable);

    List<User> findByLastname(String lastname, Sort sort);

    //用Top和First查詢限制結果大小
    User findFirstByOrderByLastnameAsc();

    User findTopByOrderByAgeDesc();

    Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);

    Slice<User> findTop3ByLastname(String lastname, Pageable pageable);

    List<User> findFirst10ByLastname(String lastname, Sort sort);
    
    //查詢存在
    boolean existsByProjectId(String projectId);

}

2 Specification查詢

     2.1 JpaSpecificationExecutor使用

            需要繼承JpaSpecificationExecutor接口,具體方法可自行查看。

@Repository
public interface AIRepository extends JpaRepository<AI, String>, JpaSpecificationExecutor<AI> {
}

2.2 提供的方法

    List<T> findAll(@Nullable Specification<T> spec);
    Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);

2.3 Specification接口

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

  public static Specification<Customer> isLongTermCustomer() {
    return new Specification<Customer>() {
      public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query,
            CriteriaBuilder builder) {

         LocalDate date = new LocalDate().minusYears(2);
         return builder.lessThan(root.get(Customer_.createdAt), date);
      }
    };
  }
  //等同於以上
  public static Specification<Customer> isLongTermCustomer() {
    return (root, query, builder) -> {
         LocalDate date = new LocalDate().minusYears(2);
         return builder.lessThan(root.get(Customer_.createdAt), date);
      }
    };
  }

  public static Specification<Customer> hasSalesOfMoreThan(MonetaryAmount value) {
    return new Specification<Customer>() {
      public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
            CriteriaBuilder builder) {

         // build query here
      }
    };
  }

}
List<Customer> customers = customerRepository.findAll(isLongTermCustomer());

這裏實現一個specification的查詢

    //join
    public static Specification<ApprovalRecord> queryProcessRecord(String approvalId) {
        return (root, query, cb) -> {
            Join<ApprovalProcess, Approval> join = root.join(ApprovalRecord_.approvalProcess).join(ApprovalProcess_.approval);
            Predicate idPredicate = cb.equal(join.get(Approval_.id), approvalId);
            Predicate statusPredicate = cb.equal(root.get(ApprovalRecord_.status), ApprovalRecordType.PENDING);
            return cb.and(idPredicate, statusPredicate);
        };
    }
    
    //and
    public static Specification<IssueConclusion> queryConclusionByIssueId(String issueId) {
        return (root, query, cb) -> {
            Predicate ownPredicate = cb.and(cb.equal(root.get(IssueConclusion_.issue).get(Issue_.id), issueId),
                cb.equal(root.get(IssueConclusion_.status), IssueConclusionStatus.WAIT_AUDIT));
            query.where(ownPredicate).orderBy(cb.desc(root.get(IssueConclusion_.lastModifiedDate)));
            return ownPredicate;
//          return query.getRestriction();
        };
    }

    // add  實現關鍵字搜索
    public static Specification<IssueConclusion> queryConclusionByStatus(IssueConclusionStatus status, String queryString) {
        return (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            predicates.add(cb.equal(root.get(IssueConclusion_.createdBy), SecurityUtils.getCurrentUserLogin().get()));
            if (status != null) {
                predicates.add(cb.equal(root.get(IssueConclusion_.status), status));
            }
            if (!StringUtils.isEmpty(queryString)) {
                predicates.add(cb.or(cb.like(root.get(IssueConclusion_.id), '%' + queryString + '%')
                    ,cb.like(root.get(IssueConclusion_.issue).get(Issue_.title), '%' + queryString + '%')));
            }
            query.where(predicates.toArray(new Predicate[predicates.size()])).orderBy(cb.desc(root.get(IssueConclusion_.lastModifiedDate)));
   //       return cb.and(predicates.toArray(new Predicate[predicates.size()]))
            return query.getRestriction();
        };
    }

 

 

發佈了34 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章