JPA - JPQL

  • 简述

    本章将向您介绍 JPQL 以及它如何与持久性单元一起工作。在本章中,示例遵循相同的包层次结构,我们在上一章中使用如下:
    JPA JPQL
  • Java 持久化查询语言

    JPQL 是 JPA 规范中定义的 Java Persistence Query Language。它用于创建针对实体的查询以存储在关系数据库中。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 表包含以下记录。
    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
    创建一个名为的类 ScalarandAggregateFunctions.java 在下面 com.jc2182.eclipselink.service 包装如下。
    
    package com.jc2182.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.jc2182.eclipselink.service 包装如下:
    
    package com.jc2182.eclipselink.service;
    import java.util.List;
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    import javax.persistence.Query;
    import com.jc2182.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
    
  • ORDER BY

    为了对 JPQL 中的记录进行排序,我们使用 ORDER BY 子句。该子句的用法与 SQL 中的用法相同,但它处理实体。遵循示例顺序。
    在下创建一个类 Ordering.java com.jc2182.eclipselink.service 包装如下:
    
    package com.jc2182.eclipselink.service;
    import java.util.List;
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    import javax.persistence.Query;
    import com.jc2182.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

    @NamedQuery 注释被定义为具有预定义的不可更改的查询字符串的查询。代替动态查询,命名查询的使用可以通过将 JPQL 查询字符串与 POJO 分开来改进代码组织。它还传递查询参数而不是将文字动态嵌入到查询字符串中,从而产生更高效的查询。
    首先给名为Employee的实体类添加@NamedQuery注解 Employee.java 在下面 com.jc2182.eclipselink.entity 包装如下:
    
    package com.jc2182.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.jc2182.eclipselink.service 包装如下:
    
    package com.jc2182.eclipselink.service;
    import java.util.List;
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    import javax.persistence.Query;
    import com.jc2182.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 方法,则它会获取整体。
    但是当您第一次尝试获取记录时,延迟获取是可能的。这样,整个记录的副本已经存储在缓存中。性能方面,延迟获取是可取的。