
- JPA 教程
- JPA - 首頁
- JPA - 簡介
- JPA - 架構
- JPA - ORM元件
- JPA - 安裝
- JPA - 實體管理器
- JPA - JPQL
- JPA - 高階對映
- JPA - 實體關係
- JPA - Criteria API
- JPA 有用資源
- JPA - 快速指南
- JPA - 有用資源
JPA - JPQL
本章介紹 JPQL 及其與持久化單元的工作方式。本章中的示例遵循與上一章相同的包層次結構,如下所示:

Java 持久化查詢語言
JPQL 是 JPA 規範中定義的 Java 持久化查詢語言。它用於建立針對儲存在關係資料庫中的實體的查詢。JPQL 基於 SQL 語法開發。但它不會直接影響資料庫。
JPQL 可以使用 SELECT 子句檢索資訊或資料,可以使用 UPDATE 子句和 DELETE 子句進行批次更新。EntityManager.createQuery() API 將支援查詢語言。
查詢結構
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 表包含以下記錄。
員工ID(Eid) | 員工姓名(Ename) | 薪水(Salary) | 職位(Deg) |
---|---|---|---|
1201 | Gopal | 40000 | 技術經理 |
1202 | Manisha | 40000 | 校對員 |
1203 | Masthanvali | 40000 | 技術撰寫人 |
1204 | Satish | 30000 | 技術撰寫人 |
1205 | Krishna | 30000 | 技術撰寫人 |
1206 | Kiran | 35000 | 校對員 |
建立一個名為 **ScalarandAggregateFunctions.java** 的類,放在 **com.tutorialspoint.eclipselink.service** 包下,如下所示。
package com.tutorialspoint.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 ax Employee Salary :40000.0
Between、And、Like 關鍵字
“Between”、“And”和“Like”是 JPQL 的主要關鍵字。這些關鍵字在查詢中的 Where 子句之後使用。
建立一個名為 **BetweenAndLikeFunctions.java** 的類,放在 **com.tutorialspoint.eclipselink.service** 包下,如下所示。
package com.tutorialspoint.eclipselink.service; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; import com.tutorialspoint.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 中的用法相同,但它處理的是實體。請遵循排序示例。
建立一個名為 **Ordering.java** 的類,放在 **com.tutorialspoint.eclipselink.service** 包下,如下所示。
package com.tutorialspoint.eclipselink.service; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; import com.tutorialspoint.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 註解定義為具有預定義不變查詢字串的查詢。與動態查詢相比,使用命名查詢可以透過將 JPQL 查詢字串與 POJO 分離來改進程式碼組織。它還會傳遞查詢引數,而不是將文字動態嵌入到查詢字串中,從而產生更高效的查詢。
首先,將 @NamedQuery 註解新增到名為 **Employee.java** 的 Employee 實體類中,該類位於 **com.tutorialspoint.eclipselink.entity** 包下,如下所示。
package com.tutorialspoint.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 + "]"; } }
建立一個名為 **NamedQueries.java** 的類,放在 **com.tutorialspoint.eclipselink.service** 包下,如下所示。
package com.tutorialspoint.eclipselink.service; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.persistence.Query; import com.tutorialspoint.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 的主要概念是在快取記憶體中建立資料庫的副本。在與資料庫進行事務處理時,它首先會影響重複資料,只有當使用實體管理器提交更改時,更改才會影響資料庫。
有兩種從資料庫中提取記錄的方法:急切提取和延遲提取。
急切提取
使用主鍵查詢記錄時提取整個記錄。
延遲提取
它檢查是否存在並使用主鍵通知它。然後,如果您呼叫該實體的任何 getter 方法,它將提取全部內容。
但是,只有在您第一次嘗試提取記錄時才有可能進行延遲提取。這樣,整個記錄的副本就已經儲存在快取記憶體中了。從效能角度來看,延遲提取更可取。