位置:首頁 > Java技術 > JPA教學 > JPA JPQL/持久化查詢語言

JPA JPQL/持久化查詢語言

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

JPA 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

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

Package Hierarchy

急切和延遲加載

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

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

預先抓取

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

延遲加載

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

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