項目中使用jpa ,第一次見查詢起來一臉蒙,這就去查下jpa查詢的方式,和概念。
jpa
概念
創建使用Java Persistence API的存儲庫是一個繁瑣的過程,需要大量時間並需要大量樣板代碼。一種推薦的方式是使用元
元模型
概念
在JPA中,標准查詢是以元模型的概念為基礎的,元模型是為具體持久化單元的受管實體定義的.這些實體可以是實體類,嵌入類或者映射的父類.提供受管實體元信息的類就是元模型類.
簡單的說就是元模型是實體類對應的一個“受管實體
- 舉個例子:
實體類 Employee(com.demo.entities包中定義)
@Entity @Table public class Employee{ private int id; private String name; private int age; @OneToMany private List<Address> addresses; // Other code… }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Employee類的標准元模型類的名字是 Employee_
import javax.annotation.Generated; import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.ListAttribute; import javax.persistence.metamodel.StaticMetamodel; @StaticMetamodel(Employee.class) public class Employee_ { public static volatile SingularAttribute<Employee, Integer> id; public static volatile SingularAttribute<Employee, Integer> age; public static volatile SingularAttribute<Employee, String> name; public static volatile ListAttribute<Employee, Address> addresses; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
Employee的每一個屬性都會使用在JPA2規范中描述的以下規則在相應的元模型類中映射:
- 元模型類的屬性全部是static和public的。
元模型類的屬性全部是static和public的。Employee的每一個屬性都會使用在JPA2規范中描述的以下規則在相應的元模型類中映射:
對於Addess這樣的集合類型,會定義靜態屬性ListAttribute< A, B> b,這里List對象b是定義在類A中類型B的對象。其它集合類型可以是SetAttribute, MapAttribute 或 CollectionAttribute 類型。
看到這應該會有個疑問,這麻煩,為什么要使用這個元模型?有啥好處?
好處肯定是有的,畢竟是標准jpa定義的東西。我這網上查了下,好處很多:
- 查詢更加類型安全
好吧,我暫時就查到這個。
criteria 查詢
為了更好的理解criteria 查詢,考慮擁有Employee實例集合的Dept實體,Employee和Dept的元模型類的代碼如下:
//All Necessary Imports @StaticMetamodel(Dept.class) public class Dept_ { public static volatile SingularAttribute<Dept, Integer> id; public static volatile ListAttribute<Dept, Employee> employeeCollection; public static volatile SingularAttribute<Dept, String> name; } //All Necessary Imports @StaticMetamodel(Employee.class) public class Employee_ { public static volatile SingularAttribute<Employee, Integer> id; public static volatile SingularAttribute<Employee, Integer> age; public static volatile SingularAttribute<Employee, String> name; public static volatile SingularAttribute<Employee, Dept> deptId; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
下面的代碼片段展示了一個criteria 查詢,它用於獲取所有年齡大於24歲的員工:
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class); Root<Employee> employee = criteriaQuery.from(Employee.class); Predicate condition = criteriaBuilder.gt(employee.get(Employee_.age), 24); criteriaQuery.where(condition); TypedQuery<Employee> typedQuery = em.createQuery(criteriaQuery); List<Employee> result = typedQuery.getResultList();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
對應的SQL: SELECT * FROM employee WHERE age > 24
CriteriaBuilder 安全查詢創建工廠
CriteriaBuilder 安全查詢創建工廠,,創建CriteriaQuery,創建查詢具體具體條件Predicate 等。
CriteriaBuilder是一個工廠對象,安全查詢的開始.用於構建JPA安全查詢.可以從EntityManager 或 EntityManagerFactory類中獲得CriteriaBuilder。
比如: CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery 安全查詢主語句
- 它通過調用 CriteriaBuilder, createQuery 或CriteriaBuilder.createTupleQuery 獲得。
- CriteriaBuilder就像CriteriaQuery 的工廠一樣。
- CriteriaQuery對象必須在實體類型或嵌入式類型上的Criteria 查詢上起作用。
- Employee實體的 CriteriaQuery 對象以下面的方式創建:
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
- 1
- 2
Root
- Root 定義查詢的From子句中能出現的類型
- Criteria查詢的查詢根定義了實體類型,能為將來導航獲得想要的結果,它與SQL查詢中的FROM子句類似。
- Root實例也是類型化的,且定義了查詢的FROM子句中能夠出現的類型。
- 查詢根實例能通過傳入一個實體類型給 AbstractQuery.from方法獲得。
- Criteria查詢,可以有多個查詢根。
- Employee實體的查詢根對象可以用以下的語法獲得 :
Root<Employee> employee = criteriaQuery.from(Employee.class);
- 1
Predicate 過濾條件
- 過濾條件應用到SQL語句的FROM子句中。
- 在criteria 查詢中,查詢條件通過Predicate 或Expression 實例應用到CriteriaQuery 對象上。
- 這些條件使用 CriteriaQuery .where 方法應用到CriteriaQuery 對象上。
- Predicate 實例也可以用Expression 實例的 isNull, isNotNull 和 in方法獲得,復合的Predicate 語句可以使用CriteriaBuilder的and, or andnot 方法構建。
- CriteriaBuilder 也是作為Predicate 實例的工廠,Predicate 對象通過調用CriteriaBuilder 的條件方法( equal,notEqual, gt, ge,lt, le,between,like等)創建。
- 這些條件使用 CriteriaQuery .where 方法應用到CriteriaQuery 對象上。
- 下面的代碼片段展示了Predicate 實例檢查年齡大於24歲的員工實例:
Predicate condition = criteriaBuilder.gt(employee.get(Employee_.age), 24); criteriaQuery.where(condition);
- 1
- 2
過Employee_元模型類age屬性,稱之為路徑表達式。若age屬性與String文本比較,編譯器會拋出錯誤,這在JPQL中是不可能的。這就是元模型的作用嗎??
Predicate[] 多個過濾條件
List<Predicate> predicatesList = new ArrayList<Predicate>(); predicatesList.add(.....Pridicate....) criteriaQuery.where(predicatesList.toArray(new Predicate[predicatesList.size()]));
OR語句(可怕)
predicatesList.add(criteriaBuilder.or(criteriaBuilder.equal(root.get(RepairOrder_.localRepairStatus), LocalRepairStatus.repairing),criteriaBuilder.equal(root.get(RepairOrder_.localRepairStatus), LocalRepairStatus.diagnos)));
忽略大小寫(全大寫)
predicatesList.add(criteriaBuilder.like(criteriaBuilder.upper(root.get(RepairShop_.shopName)), StringUtils.upperCase(StringUtils.trim(this.shopName)) + "%"));
引用原文:http://blog.csdn.net/id_kong/article/details/70225032
寫博客是為了記住自己容易忘記的東西,另外也是對自己工作的總結,文章可以轉載,無需版權。希望盡自己的努力,做到更好,大家一起努力進步!
如果有什么問題,歡迎大家一起探討,代碼如有問題,歡迎各位大神指正!