Java 持久化/Criteria
Java 持久化 Criteria API 用於透過構建基於物件的查詢定義物件來定義動態查詢,而不是使用 JPQL 的基於字串的方法。Criteria API 允許以程式設計方式構建動態查詢,與基於字串的第 4 代語言相比,它提供了更好的 Java 語言整合。
Criteria API 有兩種模式,型別限制模式和非型別模式。型別限制模式使用一組 JPA 元模型生成的類來定義類的可查詢屬性,請參見元模型。非型別模式使用字串引用類的屬性。
Criteria API 僅用於動態查詢,不能用於元資料或命名查詢。Criteria 查詢是動態查詢,因此不如靜態命名查詢或甚至動態引數化 JPQL(在某些 JPA 提供程式中可能受益於解析快取)那樣高效。
Criteria API 添加於 JPA 2.0 中。
Criteria API 刪除和更新支援添加於 JPA 2.1 中。
CriteriaBuilder是進入 Criteria API 的主要介面。一個CriteriaBuilder從一個EntityManager或一個EntityManagerFactory使用getCriteriaBuilder()API。CriteriaBuilder用於構造CriteriaQuery物件及其表示式。Criteria API 目前僅支援 select 查詢。
CriteriaBuilder定義了用於建立CriteriaQuery物件的 API
- createQuery()- 建立一個CriteriaQuery.
- createQuery(Class)- 建立一個CriteriaQuery使用泛型來避免強制轉換結果類。
- createTupleQuery()- 建立一個CriteriaQuery返回類似於 map 的Tuple物件,而不是用於多選查詢的物件陣列。請參見Tuple Queries
- createCriteriaDelete(Class)- 建立一個CriteriaDelete直接在資料庫上刪除一批物件(JPA 2.1)。
- createCriteriaUpdate(Class)- 建立一個CriteriaUpdate直接在資料庫上更新一批物件(JPA 2.1)。
CriteriaBuilder還定義了所有支援的比較運算和函式,這些運算和函式用於定義查詢的子句。
CriteriaQuery定義了資料庫 select 查詢。一個CriteriaQuery對 JPQL select 查詢的所有子句進行建模。來自一個CriteriaQuery的元素不能用於其他CriteriaQuerys。一個CriteriaQuery與EntityManager createQuery()API 一起使用以建立 JPAQuery.
CriteriaQuery定義了以下子句和選項
- distinct(boolean)- 定義查詢是否應該過濾重複結果(預設為 false)。如果使用與集合關係的連線,則應使用 distinct 以避免重複結果。
- from(Class)- 為實體類定義並返回查詢的 from 子句中的一個元素。查詢至少需要一個 from 元素才能有效。
- from(EntityType)- 為元模型實體型別定義並返回查詢的 from 子句中的一個元素。查詢至少需要一個 from 元素才能有效。
- select(Selection)- 定義查詢的 select 子句。如果未設定,則預設情況下將選擇第一個根。
- multiselect(Selection...), multiselect(List<Selection>)- 定義多選查詢。
- where(Expression), where(Predicate...)- 定義查詢的 where 子句。預設情況下,將選擇該類所有例項。
- orderBy(Order...), orderBy(List<Order>)- 定義查詢的 order 子句。預設情況下,結果未排序。
- groupBy(Expression...), groupBy(List<Expression>)- 定義查詢的 group by 子句。預設情況下,結果未分組。
- having(Expression), having(Predicate...)- 定義查詢的 having 子句。Having 允許對分組結果進行過濾。
- subQuery(Class)- 建立一個subQuery用於其他子句之一。
的Expressions, Predicates, Order元素使用CriteriaBuilderAPI 定義,並從from Root元素派生表示式。
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// Query for a List of objects.
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.where(criteriaBuilder.greaterThan(employee.get("salary"), 100000));
Query query = entityManager.createQuery(criteriaQuery);
List<Employee> result = query.getResultList();
// Query for a single object.
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.where(criteriaBuilder.equal(employee.get("id"), criteriaBuilder.parameter(Long.class, "id")));
Query query = entityManager.createQuery(criteriaQuery);
query.setParameter("id", id);
Employee result2 = (Employee)query.getSingleResult();
// Query for a single data element.
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.select(criteriaBuilder.max(employee.get("salary")));
Query query = entityManager.createQuery(criteriaQuery);
BigDecimal result3 = (BigDecimal)query.getSingleResult();
// Query for a List of data elements.
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.select(employee.get("firstName"));
Query query = entityManager.createQuery(criteriaQuery);
List<String> result4 = query.getResultList();
// Query for a List of element arrays.
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.multiselect(employee.get("firstName"), employee.get("lastName"));
Query query = entityManager.createQuery(criteriaQuery);
List<Object[]> result5 = query.getResultList();
一個選擇定義了查詢選擇的內容。一個選擇可以是任何物件表示式、屬性表示式、函式、子選擇、建構函式或聚合函式。一個別名可以為一個選擇使用alias()API。
聚合函式可以包含有關一組物件的彙總資訊。這些函式可以用來返回單個結果,也可以與groupBy一起使用來返回多個結果。
聚合函式定義在CriteriaBuilder上,幷包括
- max(Expression)- 返回所有結果的最大值。用於數值型別。
- greatest(Expression)- 返回所有結果的最大值。用於非數值型別。
- min(Expression)- 返回所有結果的最小值。用於數值型別。
- least(Expression)- 返回所有結果的最小值。用於非數值型別。
- avg(Expression)- 返回所有結果的平均值。一個Double被返回。
- sum(Expression)- 返回所有結果的總和。
- sumAsLong(Expression)- 返回所有結果的總和。一個Long被返回。
- sumAsDouble(Expression)- 返回所有結果的總和。一個Double被返回。
- count(Expression)- 返回所有結果的計數。null值不計入計數。一個Long被返回。
- countDistinct(Expression)- 返回所有不同結果的計數。null值不計入計數。一個Long被返回。
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// Count the total employees
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.select(criteriaBuilder.count(employee));
Query query = entityManager.createQuery(criteriaQuery);
Long result = query.getSingleResult();
// Maximum salary
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.select(criteriaBuilder.max(employee.get("salary"));
Query query = entityManager.createQuery(criteriaQuery);
Long result = query.getSingleResult();
的construct運算子在CriteriaBuilder上可以使用類和值從 Criteria 查詢返回資料物件。這些將不是託管物件,並且該類必須定義一個與引數和型別匹配的建構函式。建構函式查詢可用於選擇物件上的部分資料或報告資料,並返回類例項而不是物件陣列或元組。
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.select(criteriaBuilder.construct(EmpReport.class, employee.get("firstName"), employee.get("lastName"), employee.get("salary")));
Query query = entityManager.createQuery(criteriaQuery);
List<EmpReport> result = query.getResultList();
查詢的 from 子句定義了要查詢的內容。from 子句使用fromAPI onCriteriaQuery。一個Root物件從from返回,代表查詢上下文中的物件。一個Root也實現了From,並且Path. From在 from 子句中定義了一個變數,並允許聯接。Path定義了任何屬性值,並允許遍歷巢狀屬性。
Root employee = criteriaQuery.from(Employee.class);
Criteria 查詢允許多個根級物件。在執行此操作時應謹慎,因為它會導致兩個表的笛卡爾積。where 子句應確保兩個物件以某種方式聯接。
// Select the employees and the mailing addresses that have the same address.
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
Root address = criteriaQuery.from(MailingAddress.class);
criteriaQuery.multiselect(employee, address);
criteriaQuery.where(criteriaBuilder.equal(employee.get("address"), address.get("address"));
Query query = entityManager.createQuery(criteriaQuery);
List<Object[]> result = query.getResultList();
一個join操作可用於From物件以獲取要用於查詢的關係。join並不意味著將獲取關係,要獲取結果中相關物件,請使用fetch操作。
Root employee = criteriaQuery.from(Employee.class);
Join address = employee.join("address");
criteriaQuery.where(criteriaBuilder.equal(address.get("city"), city);
的join操作可用於 OneToOne、ManyToOne、OneToMany、ManyToMany 和 ElementCollection 對映。當與集合關係一起使用時,可以多次聯接相同的關係以查詢多個獨立的值。
// All employees who work on both projects.
Root employee = criteriaQuery.from(Employee.class);
Join p = employee.join("projects");
Join p2 = employee.join("projects");
criteriaQuery.where(criteriaBuilder.and(criteriaBuilder.equal(p.get("name"), projectName1), criteriaBuilder.equal(p2.get("name"), projectName2));
的fetch操作可用於From物件以在單個查詢中獲取相關物件。這避免了對每個物件的每個關係的額外查詢,並確保如果關係為 LAZY,則已獲取關係。
Root employee = criteriaQuery.from(Employee.class);
Fetch address = employee.fetch("address");
criteriaQuery.select(employee);
在使用獲取在 where 子句中應謹慎,因為它會影響結果物件關係的返回資料。物件通常應始終具有相同的資料,無論它們如何被查詢,這對快取和一致性很重要。這隻有在別名用於 where 子句中的集合關係以過濾將要獲取的相關物件時才會成為問題。不應執行此操作,但有時是可取的,在這種情況下,查詢應確保已將其設定為繞過快取。
預設情況下join和fetch是內部聯接。這意味著沒有關係的結果將從查詢結果中過濾掉。為了避免這種情況,可以使用 LEFT 將聯接定義為外部聯接JoinType作為join或fetch操作的引數。
Root employee = criteriaQuery.from(Employee.class);
Join address = employee.join("address", JoinType.LEFT);
criteriaQuery.order(address.get("city"));
查詢的 order by 子句定義了查詢結果的排序方式。order by 子句使用orderByAPI onCriteriaQuery定義。只有Order物件可以傳遞給orderBy,並且從CriteriaBuilder使用asc或descAPI。
// Order by the last and first names.
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.orderBy(criteriaBuilder.desc(employee.get("lastName")), criteriaBuilder.asc(employee.get("firstName")));
// Order by the last name, ignoring case.
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.orderBy(criteriaBuilder.asc(criteriaBuilder.upper(employee.get("lastName"))));
// Order by the address object (orders by its id).
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.orderBy(criteriaBuilder.asc(employee.get("address")));
查詢的 group by 子句允許對一組物件計算彙總資訊。group by 通常與聚合函式一起使用。group by 子句使用groupByAPI onCriteriaQuery定義,其中包含任何有效的Expression物件。
// Select the average salaries grouped by city.
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.multiselect(criteriaBuilder.avg(employee.<Number>get("salary")), employee.get("address").get("city"));
criteriaQuery.groupBy(employee.get("address").get("city"));
// Select the average salaries grouped by city, ordered by the average salary.
Root employee = criteriaQuery.from(Employee.class);
Expression avg = criteriaBuilder.avg(employee.<Number>get("salary"));
criteriaQuery.multiselect(avg, employee.get("address").get("city"));
criteriaQuery.groupBy(employee.get("address").get("city"));
criteriaQuery.orderBy(criteriaBuilder.asc(avg));
// Select employees and the count of their number of projects.
Root employee = criteriaQuery.from(Employee.class);
Expression project = employee.join("projects", JoinType.LEFT);
criteriaQuery.multiselect(e, criteriaBuilder.count(project));
criteriaQuery.groupBy(employee);
查詢的 having 子句允許過濾 group by 的結果。having 子句使用havingAPI onCriteriaQuery定義,其中包含任何Predicate物件。
// Select the average salaries grouped by city, only including cities with average salaries over 100000.
Root employee = criteriaQuery.from(Employee.class);
Expression avg = criteriaBuilder.avg(employee.<Number>get("salary"));
criteriaQuery.multiselect(avg, employee.get("address").get("city"));
criteriaQuery.groupBy(employee.get("address").get("city"));
criteriaQuery.having(criteriaBuilder.greaterThan(avg, 100000));
CriteriaUpdate定義了資料庫更新查詢。一個CriteriaUpdate對 JPQL 更新查詢的所有子句進行建模。來自一個CriteriaUpdate的元素不能用於其他CriteriaUpdates。一個CriteriaUpdate與EntityManager createQuery()API 一起使用以建立 JPAQuery。Criteria 更新只能用於批處理更新。對於對物件的定期更新,應透過事務中的 EntityManager 讀取物件,並在 Java 中修改物件,並提交更改。
CriteriaUpdate定義了以下子句和選項
- set(String, Object), set(Path, Object), set(Path, Expression)- 定義更新的 set 子句。
- where(Expression), where(Predicate...)- 定義更新的 where 子句。預設情況下,更新類的所有例項。
的Expressions, Predicates元素使用CriteriaBuilderAPI 定義,並從from Root元素派生表示式。
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// Updates the salary to 90,000 of all Employee's making more than 100,000.
CriteriaUpdate update = criteriaBuilder.createCriteriaUpdate(Employee.class);
Root employee = update.from(Employee.class);
update.set("salary", 90000);
update.where(criteriaBuilder.greaterThan(employee.get("salary"), 100000));
Query query = entityManager.createQuery(update);
int rowCount = query.executeUpdate();
// Gives all Employees a 10% raise.
CriteriaUpdate update = criteriaBuilder.createCriteriaUpdate(Employee.class);
Root employee = update.from(Employee.class);
update.set(employee.get("salary"), criteriaBuilder.sum(employee.get("salary"), criteriaBuilder.quot(employee.get("salary"), 10));
Query query = entityManager.createQuery(update);
int rowCount = query.executeUpdate();
CriteriaDelete定義了資料庫刪除查詢。一個CriteriaDelete對 JPQL 刪除查詢的所有子句進行建模。來自一個CriteriaDelete的元素不能用於其他CriteriaDelete。一個CriteriaDelete與EntityManager createQuery()API 一起使用以建立 JPAQuery. CriteriaDelete只能用於批處理刪除。對於物件的定期刪除,應透過事務中的 EntityManager 讀取物件,並透過 remove() API 刪除物件,並提交更改。
CriteriaDelete定義了以下子句和選項
- where(Expression), where(Predicate...)- 定義刪除的 where 子句。預設情況下,刪除類的所有例項。
的Expressions, Predicates元素使用CriteriaBuilderAPI 定義,並從from Root元素派生表示式。
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// Deletes all Employee's making more than 100,000.
CriteriaDelete delete = criteriaBuilder.createCriteriaDelete(Employee.class);
Root employee = delete.from(Employee.class);
delete.where(criteriaBuilder.greaterThan(employee.get("salary"), 100000));
Query query = entityManager.createQuery(delete);
int rowCount = query.executeUpdate();
// Deletes all Employees.
CriteriaDelete delete = criteriaBuilder.createCriteriaDelete(Employee.class);
Root employee = delete.from(Employee.class);
Query query = entityManager.createQuery(delete);
int rowCount = query.executeUpdate();
where 子句通常是查詢的主要部分,因為它定義了過濾返回內容的條件(謂詞)。where 子句使用whereAPI onCriteriaQuery定義,其中包含任何Predicate物件定義。一個Predicate使用比較運算子或對CriteriaBuilder的邏輯運算子獲得。該isNull, isNotNull,並且in操作也可以在Expression的邏輯運算子獲得。該not操作也可以在Predicate
| 操作 | 描述 | 示例 |
|---|---|---|
| equal, notEqual | equal | criteriaBuilder.equal(employee.get("firstName"), "Bob")
|
| lessThan, lt | 小於 | criteriaBuilder.lessThan(employee.get("salary"), 100000)
|
| greaterThan, gt | 大於 | criteriaBuilder.greaterThan(employee.get("salary"), criteriaBuilder.parameter(Integer.class, "sal"))
|
| lessThanOrEqualTo, le | 小於或等於 | criteriaBuilder.lessThanOrEqualTo(employee.get("salary"), 100000)
|
| greaterThanOrEqualTo, ge | 大於或等於 | criteriaBuilder.greaterThanOrEqualTo(employee.get("salary"), criteriaBuilder.parameter(Integer.class, "sal"))
|
| like, notLike | 評估兩個字串是否匹配,'%' 和 '_' 是有效的萬用字元,並且 ESCAPE 字元是可選的 | criteriaBuilder.like(employee.get("firstName"), "A%")
criteriaBuilder.notLike(employee.get("firstName"), "%._%", '.')
|
| between | 評估值是否在兩個值之間 | criteriaBuilder.between(employee.<String>get("firstName"), "A", "C")
|
| isNull | 將值與 null 進行比較,資料庫可能不允許或在將 = 與 null 一起使用時產生意外結果 | criteriaBuilder.isNull(employee.get("endDate"))
employee.get("endDate").isNull()
|
| in | 評估值是否包含在列表中 | criteriaBuilder.in(employee.get("firstName")).value("Bob").value("Fred").value("Joe")
employee.get("firstName").in("Bob", "Fred", "Joe")
employee.get("firstName").in(criteriaBuilder.parameter(List.class, "names")
|
| 操作 | 描述 | 示例 |
|---|---|---|
| 和 | and 將兩個或多個謂詞組合在一起 | criteriaBuilder.and(criteriaBuilder.equal(employee.get("firstName"), "Bob"), criteriaBuilder.equal(employee.get("lastName"), "Smith"))
|
| 或 | or 將兩個或多個謂詞組合在一起 | criteriaBuilder.or(criteriaBuilder.equal(employee.get("firstName"), "Bob"), criteriaBuilder.equal(employee.get("firstName"), "Bobby"))
|
| not | 否定謂詞 | criteriaBuilder.not(criteriaBuilder.or(criteriaBuilder.equal(employee.get("firstName"), "Bob"), criteriaBuilder.equal(employee.get("firstName"), "Bobby")))
criteriaBuilder.or(criteriaBuilder.equal(employee.get("firstName"), "Bob"), criteriaBuilder.equal(employee.get("firstName"), "Bobby")).not()
|
| 連線 | 表示 true 的謂詞 | Predicate where = criteriaBuilder.conjunction();
if (name != null) {
where = criteriaBuilder.and(where, criteriaBuilder.equal(employee.get("firstName"), name));
}
|
| 析取 | 表示 false 的謂詞 | Predicate where = criteriaBuilder.disjunction();
if (name != null) {
where = criteriaBuilder.or(where, criteriaBuilder.equal(employee.get("firstName"), name));
}
|
子查詢只能在 where 子句和 having 子句中使用。子查詢從CriteriaQuery使用subQuery操作建立。大多數子查詢用法將子查詢限制為返回單個結果和值,除非與CriteriaBuilder exists, all, any或some操作一起使用,或者與in操作的引數。
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// Find all manager that only manage below-average employees.
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
Subquery subQuery = criteriaQuery.subquery(Employee.class);
Root employee_2 = subQuery.from(Employee.class);
subQuery.where(criteriaBuilder.and(employee_2.get("manager").equal(e), criteriaBuilder.equal(employee_2.get("productivity"), "below average").not());
criteriaQuery.where(criteriaBuilder.exists(subQuery).not());
Query query = entityManager.createQuery(criteriaQuery)
List<Employee> = query.getResultList();
// Find the employee with the lowest salary.
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
Subquery subQuery = criteriaQuery.subquery(Employee.class);
Root employee_2 = subQuery.from(Employee.class);
subQuery.select(employee_2.get("salary"));
criteriaQuery.where(criteriaBuilder.lessThan(employee.get("salary"), criteriaBuilder.all(subQuery)));
Query query = entityManager.createQuery(criteriaQuery)
List<Employee> = query.getResultList();
可以使用parameterAPI onCriteriaBuilder定義引數。JPA 定義了命名引數和位置引數。對於命名引數,指定引數型別和名稱。對於位置引數,只指定引數型別。位置引數從位置1not0.
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.where(
criteriaBuilder.equal(employee.get("firstName"), criteriaBuilder.parameter(String.class, "first")),
criteriaBuilder.equal(employee.get("lastName"), criteriaBuilder.parameter(String.class, "last"))
);
Query query = entityManager.createQuery(criteriaQuery)
query.setParameter("first", "Bob");
query.setParameter("last", "Smith");
List<Employee> = query.getResultList();
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.where(criteriaBuilder.equal(employee.get("firstName"), criteriaBuilder.parameter(String.class)), criteriaBuilder.equal(employee.get("lastName"), criteriaBuilder.parameter(String.class)));
Query query = entityManager.createQuery(criteriaQuery)
query.setParameter(1, "Bob");
query.setParameter(2, "Smith");
List<Employee> = query.getResultList();
Criteria API 支援一些資料庫函式。所有支援的函式都在CriteriaBuilder上定義。一些函式可能不受某些資料庫支援,因為它們不符合 SQL 標準,並且沒有等效的函式。
| 函式 | 描述 | 示例 |
|---|---|---|
| diff | 減法 | criteriaBuilder.diff(employee.<Number>get("salary"), 1000)
|
| sum | 加法 | criteriaBuilder.sum(employee.<Number>get("salary"), 1000)
|
| prod | 乘法 | criteriaBuilder.prod(employee.<Number>get("salary"), 2)
|
| quot | 除法 | criteriaBuilder.quot(employee.<Number>get("salary"), 2)
|
| abs | 絕對值 | criteriaBuilder.abs(
criteriaBuilder.diff(employee.<Number>get("salary"), employee.get("manager").<Number>get("salary")))
|
| selectCase | 定義一個 case 語句 | criteriaBuilder.selectCase(employee.get("status")).
when(0, "active").
when(1, "consultant").
otherwise("unknown")
criteriaBuilder.selectCase().
when(criteriaBuilder.equal(employee.get("status"), 0), "active").
when(criteriaBuilder.equal(employee.get("status"), 1), "consultant").
otherwise("unknown")
|
| coalesce | 計算第一個非空引數的值 | criteriaBuilder.coalesce(criteriaBuilder.concat(employee.<Number>get("salary"), 0)
|
| concat | 連線兩個或多個字串值 | criteriaBuilder.concat(
criteriaBuilder.concat(employee.<String>get("firstName"), " "), employee.<String>get("lastName"))
|
| currentDate | 資料庫中的當前日期 | criteriaBuilder.currentDate()
|
| currentTime | 資料庫中的當前時間 | criteriaBuilder.currentTime()
|
| currentTimestamp | 資料庫中的當前日期時間 | criteriaBuilder.currentTimestamp()
|
| length | 字元或二進位制值的字元/位元組長度 | criteriaBuilder.length(employee.<String>get("lastName"))
|
| locate | 字串在字串中的索引,可以選擇從起始索引開始 | criteriaBuilder.locate("-", employee.<String>get("lastName"))
|
| lower | 將字串值轉換為小寫 | criteriaBuilder.lower(employee.<String>get("lastName"))
|
| mod | 計算第一個整數除以第二個整數的餘數 | criteriaBuilder.mod(employee.<Integer>get("hoursWorked"), 8)
|
| nullif | 如果第一個引數等於第二個引數,則返回 null,否則返回第一個引數 | criteriaBuilder.nullif(employee.<Number>get("salary"), 0)
|
| sqrt | 計算數字的平方根 | criteriaBuilder.sqrt(employee.<Number>get("salary"))
|
| substring | 字串的子字串,從索引開始,可以選擇子字串的大小 | criteriaBuilder.substring(employee.<String>get("lastName"), 0, 2)
|
| trim | 從字串中修剪開頭、結尾或兩端的空格或可選的修剪字元 | criteriaBuilder.trim(TrimSpec.TRAILING, employee.<String>get("lastName"))
criteriaBuilder.trim(employee.<String>get("lastName"))
criteriaBuilder.trim(TrimSpec.LEADING, '-', employee.<String>get("lastName"))
|
| upper | 將字串值轉換為大寫 | criteriaBuilder.upper(employee.<String>get("lastName"))
|
Criteria API 定義了一些特殊操作,這些操作不是資料庫函式,但在 JPA 中具有特殊含義。其中一些操作是在CriteriaBuilder上定義的,而另一些則是在特定表示式介面上定義的。
| 函式 | 描述 | 示例 |
|---|---|---|
| index | 排序列表元素的索引,僅在對映中使用 @OrderColumn 時支援, 在ListJoin介面上定義,該介面從From元素使用joinList操作獲得 |
Root employee = criteriaQuery.from(Employee.class);
ListJoin toDo = employee.joinList("toDoList");
criteriaQuery.multiselect(e, toDo);
criteriaQuery.where(criteriaBuilder.equal(toDo.index(), 1));
|
| key, value | 對映元素的鍵或值,在MapJoin介面上定義,該介面從From元素使用joinMap操作獲得 | Root employee = criteriaQuery.from(Employee.class);
MapJoin p = employee.joinMap("priorities");
criteriaQuery.multiselect(e, p.value());
criteriaQuery.where(criteriaBuilder.equal(p.key(), "high"))
|
| size | 集合關係的大小,這將計算為子查詢,在CriteriaBuilder | criteriaBuilder.greaterThan(criteriaBuilder.size(employee.<Collection>get("managedEmployees")), 2)
|
| isEmpty, isNotEmpty | 上定義,它計算為真,如果集合關係為空或不為空,這將計算為子查詢,在CriteriaBuilder | criteriaBuilder.isEmpty(employee.<Collection>get("managedEmployees"))
|
| isMember, isNotMember | 上定義,它計算為真,如果集合關係包含該值,這將計算為子查詢,在CriteriaBuilder | criteriaBuilder.isMember("write code", employee.<Collection>get("responsibilities"))
|
| type | 繼承鑑別器值,在任何Path表示式 | criteriaBuilder.equal(p.type(), LargeProject.class)
|
| as | 可用於將非型別化表示式轉換為型別化表示式,EclipseLink 還允許將繼承型別向下轉換 | criteriaBuilder.mod(employee.get("id").as(Integer.class), 2)
criteriaBuilder.greaterThan(p.as(LargeProject.class).get("budget"), 1000000)
|
| function | 呼叫資料庫特定函式,在CriteriaBuilder | criteriaBuilder.greaterThan(criteriaBuilder.function("TO_NUMBER", Number.class, p.get("areaCode")), 613)
|
JPA 定義了一個元模型,它可以在執行時用於查詢有關 ORM 對映元資料的的資訊。元模型包括類對映屬性的列表,以及它們的對映型別和基數。元模型可與 Criteria API 一起使用,以替代使用字串引用類屬性。
JPA 定義了一組_類,這些類將由 JPA 提供程式或 IDE 生成,從而在編譯時訪問元模型。這允許在 Criteria API 中使用型別化的靜態變數。這可以透過在編譯時而不是在測試期間捕獲查詢問題,來減少應用程式程式碼中出現拼寫錯誤或無效查詢的可能性。但是,它確實增加了開發過程的複雜性,因為元模型靜態類需要生成併成為開發週期的一部分。
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root<Employee> employee = criteriaQuery.from(entityManager.getMetamodel().entity(Employee.class));
criteriaQuery.where(criteriaBuilder.equal(employee.get(Employee_.firstName), "Bob"), criteriaBuilder.equal(employee.get(Employee_.lastName), "Smith"));
Query query = entityManager.createQuery(criteriaQuery)
List<Employee> = query.getResultList();
一個Tuple定義一個多選查詢結果。通常,JPA 多選查詢會返回一個物件陣列,但物件陣列不是一個非常有用的資料結構。一個Tuple是一個類似於對映的結構,它允許透過名稱或索引檢索結果。
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> criteriaQuery = criteriaBuilder.createTupleQuery();
Root employee = criteriaQuery.from(Employee.class);
criteriaQuery.multiselect(employee.get("firstName").alias("first"), employee.get("lastName").alias("last"));
Query query = entityManager.createQuery(criteriaQuery);
List<Tuple> results = query.getResultList();
String first = results.get(0).get("first");
String last = results.get(0).get("last");