首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring Data JPA 動態查詢實戰:Criteria API 與 Specification 兩大核心方案詳解

     編輯:Java 相關知識

業務開發中常面臨多條件組合查詢需求,若為每種組合寫專用方法會導致代碼爆炸。Spring Data JPA 提供兩種基於 Criteria API 的動態查詢方案,本文從原理到實戰全面對比。

Criteria API 核心優勢

  • 類型安全:元模型(UserInfo_)編譯期檢查屬性名,避免運行時拼接 SQL 錯誤
  • 跨數據庫可移植:自動生成適配 MySQL/PostgreSQL/Oracle 等方言的 SQL
  • 面向對象構建:用 CriteriaQuery、Predicate 替代字符串拼接

方案一:手動構建 CriteriaQuery(底層 API)

適用於需要精細控制查詢結構(如動態 SELECT 字段、複雜 JOIN)的場景。

public List<UserInfo> getUserInfo(String name, int age, int high) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<UserInfo> query = cb.createQuery(UserInfo.class);
    Root<UserInfo> root = query.from(UserInfo.class);

    Predicate predicate = null;
    if (name != null) {
        Predicate p = cb.equal(root.get(UserInfo_.name), name);
        predicate = (predicate == null) ? p : cb.and(predicate, p);
    }
    if (age != 0) {
        Predicate p = cb.equal(root.get(UserInfo_.age), age);
        predicate = (predicate == null) ? p : cb.and(predicate, p);
    }
    if (high != 0) {
        Predicate p = cb.equal(root.get(UserInfo_.high), high);
        predicate = (predicate == null) ? p : cb.and(predicate, p);
    }
    query.where(predicate);
    return em.createQuery(query).getResultList();
}

方案二:JpaSpecificationExecutor + Specification(高級封裝)

DAO 繼承 JpaSpecificationExecutor<T>,自動獲得分頁、排序、動態條件查詢能力,無需手動管理 EntityManager。

public interface UserInfoDao extends PagingAndSortingRepository<UserInfo, String>, 
        JpaSpecificationExecutor<UserInfo> {}

構建 Specification 匿名類,將條件構建邏輯封裝:

public static Specification<UserInfo> getSpec(final String name, final int age, final int high) {
    return (root, query, cb) -> {
        Predicate predicate = null;
        if (name != null) predicate = cb.and(predicate, cb.equal(root.get(UserInfo_.name), name));
        if (age != 0) predicate = cb.and(predicate, cb.equal(root.get(UserInfo_.age), age));
        if (high != 0) predicate = cb.and(predicate, cb.equal(root.get(UserInfo_.high), high));
        return predicate;
    };
}

調用極簡潔:

List<UserInfo> list = userInfoDao.findAll(getSpec("張三", 25, 180));
Page<UserInfo> page = userInfoDao.findAll(getSpec(null, 0, 0), PageRequest.of(0, 10, Sort.by("age").descending()));

方案對比與選型建議

維度手動 CriteriaQuerySpecification
靈活度極高(控制 SELECT/JOIN/GROUP BY)僅 WHERE 條件動態
代碼量較多極少
分頁排序手動實現內置支持
適用場景複雜報表、多表關聯常規業務條件查詢

元模型生成提示

使用 @StaticMetamodel 註解的類(如 UserInfo_)可由 hibernate-jpamodelgen 編譯期自動生成,避免手寫維護成本。

項目源碼下載:springdatajpademo_jb51.rar

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved