Spring Boot 3 使用 Hibernate JPA 碰到動態條件,比如,UI上有四個欄位,使用可能輸入的條件數量不等,如何可以依照不同數量的條件進行查詢呢?
需要使用 JpaSpecificationExecutor 這個介面。
JpaSpecificationExecutor 有哪些 method
public interface JpaSpecificationExecutor<T> {
Optional<T> findOne(@Nullable Specification<T> spec);
List<T> findAll(@Nullable Specification<T> spec);
Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);
List<T> findAll(@Nullable Specification<T> spec, Sort sort);
long count(@Nullable Specification<T> spec);
}
JpaSpecificationExecutor 怎麼用
以上個文章中的 dao 為例,增加介面的實作
@Repository
public interface MyBookDao extends JpaRepository<MyBook, Long> , JpaSpecificationExecutor<MyBook>
在 controller 或是 service 增加動態條件的查詢 method
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Predicate;
......
@GetMapping("mywhere")
public Map mywhere() {
Map rs = new HashMap();
List<MyBook> list=findWithCondition("第一本書",null);
List<MyBookVo> listVo = new ArrayList<>();
for(MyBook book:list) {
MyBookVo vo = new MyBookVo();
BeanUtils.copyProperties(book, vo);//複製資廖
listVo.add(vo);
}
rs.put("success", true);
rs.put("book", listVo);
return rs;
}
public List<MyBook> findWithCondition(String name, String email) {
Specification<MyBook> spec = (root, query, builder) -> {
List<Predicate> predicates = new ArrayList<>();
if (name != null) {
Expression<String> nameExp = root.get("name").as(String.class);
predicates.add(builder.equal(nameExp, name));
}
if (email != null) {
Expression<String> publishingHouseExp = root.get("publishingHouse").as(String.class);
predicates.add(builder.equal(publishingHouseExp, email));
}
query.where(builder.and(predicates.toArray(new Predicate[0])));
return query.getRestriction();
};
return myBookDao.findAll(spec);
}
在瀏覽器上執行 http://localhost:8080/MyBook/mywhere

https://jakarta.ee/learn/docs/jakartaee-tutorial/current/persist/persistence-criteria/persistence-criteria.html
criteria 參考