Try   HackMD

在 Spring Data JPA 下使用 Criteria API

tags: Spring java jpa persistence

在實際應用中,資料查詢的條件常常是多變性的,也就是無法100%完全預測使用者所下的限制,所以得使用 Criteria API 以滿足ㄍㄜˋㄓㄨㄥˇㄕㄞㄒㄩㄢˇㄒㄩㄑㄧㄡˊ。首先 repository 得繼承 JpaSpecificationExecutor<T>JavaDoc

@Repository
public interface SomeoneRepository extends JpaRepository<Someone, Long>, JpaSpecificationExecutor<Someone> {
}

使其支援

  • public long count(Specification<T> spec)
    根據 Specification 回傳符合的資料集數量。
  • public List<T> findAll(Specification<T> spec)
    根據 Specification 回傳符合的資料集。
  • public Page<T> findAll(Specification<T> spec, Pageable pageable)
    根據 SpecificationPageable 回傳符合的資料 Page
  • public List<T> findAll(Specification<T> spec, Sort sort)
    根據 SpecificationSort 回傳符合的資料集。
  • public Optional<T> findOne(Specification<T> spec)
    根據 Specification 回傳符合的資料,若沒有符合的資料則回傳 Optional.empty()

等 methods。PagePageable請參考此筆記,那什麼是Specification呢?

建立 Specification


	private SomeoneSpecifications() {
	}

	/**
	 * @param nicknames 模糊查詢-會員名稱
	 * @param tages 查詢-會員名稱
	 * @return
	 */
	public static Specification<Someone> likeNickname(Set<String> nicknames, Set<String> tages) {
		return new Specification<Someone>() {

			@SuppressWarnings("FieldNameHidesFieldInSuperclass")
			private static final long serialVersionUID = 6644524130903161741L;
            
			@Override
			public Predicate toPredicate(Root<Someone> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				Set<Predicate> set = new HashSet<>();
				for (String nickname : nicknames) {
                                    //使用 like 模糊查詢會員名稱
                                    set.add(criteriaBuilder.like(root.get("nickname"), "%" + nickname + "%"));
				}
				if (!tages.isEmpty()) {
                                      //使用 in 查詢資料
					set.add(root.get("nickname").in(tages));
				}
				Predicate[] predicates = new Predicate[set.size()];
				predicates = set.toArray(predicates);
				return criteriaBuilder.or(predicates);
			}
		};
	}
}

實作的 Method 參數介紹

在 Controller 可以在 Repository 呼叫 Specifications class method

someoneRepository.findAll(SomeoneSpecifications.likeNickname(titles, tags);

參考來源

https://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-four-jpa-criteria-queries/
https://developer.ibm.com/articles/j-typesafejpa/
https://javaee.github.io/tutorial/toc.html