JPQL

优质
小牛编辑
134浏览
2023-12-01

本章将介绍JPQL及其如何与持久性单元一起使用。 在本章中,示例遵循相同的包层次结构,我们在前一章中使用了如下所示:

JPA 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 ...]

标量函数和聚合函数 (calar and Aggregate Functions)

标量函数根据输入值返回结果值。 聚合函数通过计算输入值返回结果值。

请遵循前面章节中使用的相同示例员工管理。 在这里,我们将使用JPQL的标量和聚合函数来检查服务类。

我们假设jpadb.employee表包含以下记录。

开斋节易名薪水DEG
1201Gopal40000技术经理
1202Manisha40000证明读者
1203Masthanvali40000技术文件撰稿人
1204Satish30000技术文件撰稿人
1205Krishna30000技术文件撰稿人
1206Kiran35000证明读者

cn.xnip.eclipselink.service包下创建一个名为ScalarandAggregateFunctions.java的类,如下所示。

package cn.xnip.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'是JPQL的主要关键字。 这些关键字在查询中的Where子句之后使用。

cn.xnip.eclipselink.service包下创建一个名为BetweenAndLikeFunctions.java的类,如下所示:

package cn.xnip.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import cn.xnip.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

Ordering

要在JPQL中对记录进行排序,我们使用ORDER BY子句。 此子句的用法与SQL中的用法相同,但它处理实体。 按示例顺序执行。

cn.xnip.eclipselink.service包下创建一个类Ordering.java,如下所示:

package cn.xnip.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import cn.xnip.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注释添加到cn.xnip.eclipselink.entity包下名为Employee.java的Employee实体类中,如下所示:

package cn.xnip.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 + "]";
   }
}

cn.xnip.eclipselink.service包下创建一个名为NamedQueries.java的类,如下所示:

package cn.xnip.eclipselink.service;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import cn.xnip.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方法,那么它将获取整个。

但是,当您尝试第一次获取记录时,可以进行延迟提取。 这样,整个记录的副本已经存储在高速缓冲存储器中。 性能方面,懒惰的提取是更可取的。