JPA JPQL


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

JPA JPQL

Java持久性查询语言

JPQL是JPA规范中定义的Java持久性查询语言。它用于创建对实体的查询以存储在关系数据库中。JPQL是基于SQL语法开发的。但它不会直接影响数据库。

JPQL可以使用SELECT子句检索信息或数据,可以使用UPDATE子句和DELETE子句进行批量更新。EntityManager.createQuery()API将支持查询语言。

查询结构

JPQL语法与SQL的语法非常相似。SQL像语法一样是一个优点,因为SQL是一种简单的结构化查询语言,许多开发人员在应用程序中使用它。SQL直接针对关系数据库表,记录和字段,而JPQL适用于Java类和实例。

例如,与SQL一样,JPQL查询可以从数据库中检索实体对象而不是字段结果集。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 Technical Manager
1202 Manisha 40000 Proof Reader
1203 Masthanvali 40000 Technical Writer
1204 Satish 30000 Technical Writer
1205 Krishna 30000 Technical Writer
1206 Kiran 35000 Proof Reader

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

package com.CodingDict.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’, and ‘Like’是JPQL的主要关键字。这些关键字在查询中的Where子句之后使用。

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

package com. CodingDict.eclipselink.service;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.CodingDict.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中的用法相同,但它处理实体。按照例子的顺序。

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

package com.CodingDict.eclipselink.service;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.CodingDict.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.CodingDict.eclipselink.entity 包下名为 Employee.java 的Employee实体类中,如下所示: **

package com. CodingDict.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.CodingDict.eclipselink.service 包下创建一个名为 NamedQueries.java 的类,如下所示: **

package com. CodingDict.eclipselink.service;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import com.CodingDict.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方法,那么它将获取整体。

但是,当您尝试第一次获取记录时,懒惰获取是可能的。这样,整个记录的副本已经存储在高速缓冲存储器中。性能明智,懒惰取指令是可取的。