JPA JPQL/持久化查詢語言

本章介紹有關JPQL和它的工作原理與持久性單元。在這一章中,給出的例子遵循相同的包層次結構,和我們在前面的章節中使用一樣。

JPA

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

加入上述所有類後,包層次結構如下所示:

Package

急切和延遲加載

JPA中最重要的概念是爲了使數據庫的副本在高速緩衝存儲器中。雖然有一個數據庫事務,但JPA首先創建一個重複的數據集,只有當它使用實體管理提交,所做的更改影響到數據庫中。

從數據庫中獲取記錄有兩種方式。

預先抓取

在預先抓取,相關的子對象獲取一個特定的記錄自動上傳。

延遲加載

在延遲裝載,涉及的對象不會自動上傳,除非你特別要求他們。首先,它檢查相關對象和通知可用性。以後,如果調用任何實體的getter方法,那麼它獲取的所有記錄。

延遲裝載可能在第一次嘗試獲取記錄。這樣一來,在整個記錄的副本已經被存儲在高速緩衝存儲器中。性能方面,延遲裝載最好。