JPA JPQL/持久化查詢語言
本章介紹有關JPQL和它的工作原理與持久性單元。在這一章中,給出的例子遵循相同的包層次結構,和我們在前麵的章節中使用一樣。
Java持久化查詢語言
JPQL代表Java持久化查詢語言。它被用來創建針對實體的查詢存儲在關係數據庫中。 JPQL是基於SQL語法的發展。但它不會直接影響到數據庫。
JPQL可以檢索使用SELECT子句中的數據,可以使用 UPDATE子句做批量UPDATE和DELETE子句。
查詢結構
JPQL語法非常類似於SQL語法。SQL的語法是一個優勢,因為SQL很簡單,被廣泛使用。 SQL工作直接針對關係數據庫表,記錄和字段,而JPQL適用於Java類和實例。
例如,JPQL查詢可以檢索實體對象,而不是從一個數據庫中設置字段結果,作為與SQL。該JPQL查詢結構如下。
SELECT ... FROM ... [WHERE ...] [GROUP BY ... [HAVING ...]] [ORDER BY ...]
JPQL的結構,DELETE和UPDATE查詢,如下所示。
DELETE FROM ... [WHERE ...] UPDATE ... SET ... [WHERE ...]
標量和聚合函數
標量函數返回基於輸入值所得的數值。集合函數,通過計算輸入值返回的結果值。
我們將使用相同的例子員工管理,在前麵的章節。在這裡將通過使用JPQL的標量和聚合函數的服務類。
讓我們假定 jpadb.employee 表包含下述記錄。
Eid | Ename | Salary | Deg |
---|---|---|---|
1201 | Gopal | 40000 | 技術經理 |
1202 | Manisha | 40000 | 接待員 |
1203 | Masthanvali | 40000 | 技術作家 |
1204 | Satish | 30000 | 技術作家 |
1205 | Krishna | 30000 | 技術作家 |
1206 | Kiran | 35000 | 接待員 |
創建一個在 com.yiibai.eclipselink.service 包命名為 ScalarandAggregateFunctions.java類如下。
package com.yiibai.eclipselink.service; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; public class ScalarandAggregateFunctions { public static void main( String[ ] args ) { EntityManagerFactory emfactory = Persistence. createEntityManagerFactory( "Eclipselink_JPA" ); EntityManager entitymanager = emfactory. createEntityManager(); //Scalar function Query query = entitymanager. createQuery("Select UPPER(e.ename) from Employee e"); List<String> list=query.getResultList(); for(String e:list) { System.out.println("Employee NAME :"+e); } //Aggregate function Query query1 = entitymanager. createQuery("Select MAX(e.salary) from Employee e"); Double result=(Double) query1.getSingleResult(); System.out.println("Max Employee Salary :"+result); } }
編譯和執行上麵的程序,在Eclipse IDE的控製台麵板上會得到以下輸出。
Employee NAME :GOPAL Employee NAME :MANISHA Employee NAME :MASTHANVALI Employee NAME :SATISH Employee NAME :KRISHNA Employee NAME :KIRAN Max Employee Salary :40000.0
Between, And, Like 關鍵詞
Between, And, 和Like是JPQL的主要關鍵字。這些關鍵字在查詢子句後使用。
創建一個名為 BetweenAndLikeFunctions.java 類在 com.yiibai.eclipselink.service包下,如下所示:
package com.yiibai.eclipselink.service; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; import com.yiibai.eclipselink.entity.Employee; public class BetweenAndLikeFunctions { public static void main( String[ ] args ) { EntityManagerFactory emfactory = Persistence. createEntityManagerFactory( "Eclipselink_JPA" ); EntityManager entitymanager = emfactory. createEntityManager(); //Between Query query = entitymanager. createQuery( "Select e " + "from Employee e " + "where e.salary " + "Between 30000 and 40000" ) List<Employee> list=(List<Employee>)query.getResultList( ); for( Employee e:list ) { System.out.print("Employee ID :"+e.getEid( )); System.out.println("\t Employee salary :"+e.getSalary( )); } //Like Query query1 = entitymanager. createQuery("Select e " + "from Employee e " + "where e.ename LIKE 'M%'"); List<Employee> list1=(List<Employee>)query1.getResultList( ); for( Employee e:list1 ) { System.out.print("Employee ID :"+e.getEid( )); System.out.println("\t Employee name :"+e.getEname( )); } } }
編譯並執行上述程序後,將在Eclipse IDE的控製台麵板下麵輸出以下內容。
Employee ID :1201 Employee salary :40000.0 Employee ID :1202 Employee salary :40000.0 Employee ID :1203 Employee salary :40000.0 Employee ID :1204 Employee salary :30000.0 Employee ID :1205 Employee salary :30000.0 Employee ID :1206 Employee salary :35000.0 Employee ID :1202 Employee name :Manisha Employee ID :1203 Employee name :Masthanvali
排序
要排序JPQL中的記錄,我們使用ORDER BY子句。這一個子句的使用類似於SQL中的用法,但它涉及的實體。下麵的示例演示了如何使用ORDER BY子句。
在com.yiibai.eclipselink.service包中創建類 Ordering.java 如下:
package com.yiibai.eclipselink.service; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; import com.yiibai.eclipselink.entity.Employee; public class Ordering { public static void main( String[ ] args ) { EntityManagerFactory emfactory = Persistence. createEntityManagerFactory( "Eclipselink_JPA" ); EntityManager entitymanager = emfactory. createEntityManager(); //Between Query query = entitymanager. createQuery( "Select e " + "from Employee e " + "ORDER BY e.ename ASC" ); List<Employee> list=(List<Employee>)query.getResultList( ); for( Employee e:list ) { System.out.print("Employee ID :"+e.getEid( )); System.out.println("\t Employee Name :"+e.getEname( )); } } }
編譯和執行上麵的程序,在Eclipse IDE的控製台麵板會產生下麵的輸出。
Employee ID :1201 Employee Name :Gopal Employee ID :1206 Employee Name :Kiran Employee ID :1205 Employee Name :Krishna Employee ID :1202 Employee Name :Manisha Employee ID :1203 Employee Name :Masthanvali Employee ID :1204 Employee Name :Satish
命名查詢
@NamedQuery注解被定義為一個預定義的查詢字符串,它是不可改變的查詢。相反,動態查詢,命名查詢可以通過POJO分離JPQL查詢字符串提高代碼的組織。它也傳送的查詢參數,而不是動態地嵌入文本到查詢字符串,並因此產生更高效的查詢。
首先,@NamedQuery注解添加到com.yiibai.eclipselink.entity包中的 Employee實體,類名為Employee.java下,如下所示:
package com.yiibai.eclipselink.entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.NamedQuery; import javax.persistence.Table; @Entity @Table @NamedQuery(query = "Select e from Employee e where e.eid = :id", name = "find employee by id") public class Employee { @Id @GeneratedValue(strategy= GenerationType.AUTO) private int eid; private String ename; private double salary; private String deg; public Employee(int eid, String ename, double salary, String deg) { super( ); this.eid = eid; this.ename = ename; this.salary = salary; this.deg = deg; } public Employee( ) { super(); } public int getEid( ) { return eid; } public void setEid(int eid) { this.eid = eid; } public String getEname( ) { return ename; } public void setEname(String ename) { this.ename = ename; } public double getSalary( ) { return salary; } public void setSalary(double salary) { this.salary = salary; } public String getDeg( ) { return deg; } public void setDeg(String deg) { this.deg = deg; } @Override public String toString() { return "Employee [eid=" + eid + ", ename=" + ename + ", salary=" + salary + ", deg=" + deg + "]"; } }
創建一個名為com.yiibai.eclipselink.service包下的NamedQueries.java類,如下所示:
package com.yiibai.eclipselink.service; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; import com.yiibai.eclipselink.entity.Employee; public class NamedQueries { public static void main( String[ ] args ) { EntityManagerFactory emfactory = Persistence. createEntityManagerFactory( "Eclipselink_JPA" ); EntityManager entitymanager = emfactory. createEntityManager(); Query query = entitymanager.createNamedQuery( "find employee by id"); query.setParameter("id", 1204); List<Employee> list = query.getResultList( ); for( Employee e:list ) { System.out.print("Employee ID :"+e.getEid( )); System.out.println("\t Employee Name :"+e.getEname( )); } } }
經過編譯和執行上麵的程序,在Eclipse IDE的控製台麵板上會得到下麵的輸出。
Employee ID :1204 Employee Name :Satish
加入上述所有類後,包層次結構如下所示:
急切和延遲加載
JPA中最重要的概念是為了使數據庫的副本在高速緩衝存儲器中。雖然有一個數據庫事務,但JPA首先創建一個重複的數據集,隻有當它使用實體管理提交,所做的更改影響到數據庫中。
從數據庫中獲取記錄有兩種方式。
預先抓取
在預先抓取,相關的子對象獲取一個特定的記錄自動上傳。
延遲加載
在延遲裝載,涉及的對象不會自動上傳,除非你特彆要求他們。首先,它檢查相關對象和通知可用性。以後,如果調用任何實體的getter方法,那麼它獲取的所有記錄。
延遲裝載可能在第一次嘗試獲取記錄。這樣一來,在整個記錄的副本已經被存儲在高速緩衝存儲器中。性能方麵,延遲裝載最好。