在 Java EE应用程序中使用JPQL

翻译 2017年09月29日 10:28:10

     如果您使用过数据库,您很可能已经使用过 SQL,这个标准的工具提供了一系列语句,用于访问和操作关系数据库中的信息。实际上,JPQL 和 SQL 有很多相似之处。归根结底,它们都用于访问和操作数据库数据。而且,二者都使用非过程语句 — 通过特殊解释程序识别的命令。此外,JPQL 在语法上与 SQL 也相似。

   JPQL 和 SQL 的主要区别在于,前者处理 JPA 实体,后者直接处理关系数据。作为 Java 开发人员,您可能还有兴趣了解使用 JPQL 与 SQL/JDBC 的不同,无需在 Java 代码中使用 JDBC API — 容器在幕后为您完成了所有这些工作。

   通过 JPQL,您可以使用 SELECT、UPDATE 或 DELETE 这三条语句之一来定义查询。值得注意的是,EntityManager API 接口提供的方法也可用于对实体执行检索、更新和删除操作。具体来说,是 find、merge 和 remove 方法。然而,这些方法的使用通常限于单个实体实例,当然,级联生效时除外。而 JPQL 语句则没有这样的限制 — 您可以定义对若干组实体进行批量更新和删除操作,并定义查询返回若干组实体实例。

  要从 Java 代码内发出 JPQL 查询,您需要利用 EntityManager API 和 Query API 的相应方法,执行以下一般步骤:

  1. 使用注入或通过 EntityManagerFactory 实例显式获取一个 EntityManager 实例。
  2. 通过调用相应 EntityManager 的方法(如 createQuery),创建一个 Query 实例。
  3. 如果有查询参数,使用相应 Query 的 setParameter 方法进行设置。
  4. 如果需要,使用 setMaxResults 和/或 setFirstResult Query 的方法设置要检索的实例的最大数量和/或指定检索的起始实例位置。
  5. 如果需要,使用 setHint Query 的方法设置供应商特定的提示。
  6. 如果需要,使用 setFlushMode Query 的方法设置查询执行的刷新模式,覆盖实体管理器的刷新模式。
  7. 使用相应 Query 的方法 getSingleResult 或 getResultList 执行查询。可是,如果进行更新或删除操作,您必须使用 executeUpdate 方法,它返回已更新或删除的实体实例的数量。
EntityManager 接口方法以及 Query API 接口方法的完整列表可以在以下 Enterprise JavaBeans 3.0 规范中找到:Java 持久性 API 文档(JSR-220 的一部分)。

既然您已经对如何创建以及发出 JPQL 查询有了大致了解,您可能希望看一些实际的示例。以下代码片段摘自一个 servlet 的 doGet 方法,该方法使用 JPQL 查询获取有关与查询中指定的 Customer 实体相关的底层关系表中存储的所有客户的信息。

...
    @PersistenceUnit
    private EntityManagerFactory emf;
    public void doGet(
...
        EntityManager em = emf.createEntityManager();
        PrintWriter out = response.getWriter();
        List<Customer> arr_cust = (List<Customer>)em.createQuery("SELECT c FROM Customer c")
                              .getResultList(); 
        out.println("List of all customers: "+"<br/>");
Iterator i = arr_cust.iterator();
Customer cust;
while (i.hasNext()) {
cust = (Customer) i.next();
out.println(cust.getCust_id()+"<br/>");
out.println(cust.getCust_name()+"<br/>");
out.println(cust.getEmail()+"<br/>");
out.println(cust.getPhone()+"<br/>");
out.println("----------------" + "<br/>");
        }
...

  当然,这里让人关注的是 EntityManager 实例的 createQuery 方法和 Query 实例的 getResultList 方法。EntityManager 的 createQuery 用于创建 Query 实例,然后该实例的 getResultList 方法用于执行作为参数传递给 createQuery 的 JPQL 查询。正如您可能已经猜到的那样,Query 的 getResultList 方法以 List 形式返回查询的结果,在这个特定示例中,将 List 的元素转换为 Customer 类型。

如果您需要检索单个结果,Query API 接口提供了 getSingleResult 方法,如以下示例所示。然而,请注意,如果您返回多个结果,使用 getSingleResult 将引发异常。

        该示例还说明了如何使用 Query 的 setParameter 方法,通过该方法,您可以将参数值绑定到某个查询参数。使用 setParameter,您既可以绑定命名参数也可以绑定位置参数。但是,您在此处绑定的是一个命名参数。

...
        Integer cust_id =2;
        Customer cust = (Customer)em.createQuery("SELECT c FROM Customer c WHERE c.cust_id=:cust_id")
                              .setParameter("cust_id", cust_id)
                              .getSingleResult(); 
        out.println("Customer with id "+cust.getCust_id()+" is: "+ cust.getCust_name()+"<br/>");
...
值得注意的是,如果检索单个实体实例,SELECT JPQL 语句并不是唯一的选择。您还可以使用 EntityManager 的 find 方法,通过该方法,您可以根据实体的 ID(作为参数传入)检索单个实体实例。

在某些情况下,您可能只需检索目标实体实例中的某些信息,针对特定的实体字段定义 JPQL 查询。如果您只需检索此处查询的 Customer 实体实例的 cust_name 字段的值,上面的代码片段应改为:

...
        Integer cust_id =2;
        String cust_name = (String)em.createQuery("SELECT c.cust_name FROM Customer c WHERE c.cust_id=:cust_id")
                              .setParameter("cust_id", cust_id)
                              .getSingleResult(); 
        out.println("Customer with id "+cust_id+" is: "+cust_name+"<br/>");
...
同样,要获取客户名称的完整列表,可以使用以下代码:
...
        List<String> arr_cust_name = (List<String>)em.createQuery("SELECT c.cust_name FROM Customer c")
                              .getResultList(); 
        out.println("List of all customers: "+"<br/>");
Iterator i = arr_cust_name.iterator();
String cust_name;
while (i.hasNext()) {
cust_name = (String) i.next();
out.println(cust_name+"<br/>");
        }
...
重新再看 SQL,您可能想起 SQL 查询的选择列表可以由 FROM 子句中指定的表中的若干个字段组成。在 JPQL 中,您还可以使用组成的选择列表,仅从感兴趣的实体字段中选择数据。但是,在这种情况下,您需要创建一个类,将查询结果赋予该类。

  在下一小节中,您将看到一个 JPQL 联接查询的示例,该查询的选择列表由源自多个实体的字段组成。

使用Eclipse开发Java EE应用

下面以开发一个简单的Web应用为例,向读者介绍通过Eclipse开发Java EE应用的通用步骤。此处介绍的Eclipse是以Eclipse IDE for Java EE DeveIopers为例,...
  • wolaiye320
  • wolaiye320
  • 2016年06月12日 16:30
  • 620

JPA 学习篇(五) 浅谈JPQL 查询时注意事项

1. Java Persistence Query  Language : Java 定义的一套面向对象的查询语言。通过JPA ,开发者可以编写在ORM 映射型框架上具有可移植性的查询。 2. JPQ...
  • zgf19930504
  • zgf19930504
  • 2015年11月04日 17:50
  • 875

JPQL查询实例

前面学习了JPQL语言和Query接口。这里学习一下如果通过JPQL和Query接口进行数据的查询、更新和删除。【1】普通查询首先说明一下FROM子句和Select-FROM。from 子句是查询语句...
  • J080624
  • J080624
  • 2017年12月12日 11:11
  • 149

Java EE 快速入门

分享一些边学边做项目的Java EE经历
  • webzhuce
  • webzhuce
  • 2016年11月05日 23:06
  • 2072

JPA开发总结<二>--基本操作+JPQL查询

首先看下使用JPA规范的注解方式模板(代码中解释很详细): @Entity(name="person") public class Person { //GenerationType为AUTO是权...
  • zeb_perfect
  • zeb_perfect
  • 2015年01月02日 21:12
  • 1709

关于JPQL中的in的用法 指教?

目前使用Maven管理  Spring-Jpa 做的项目。在dao层使用的jpql查询  @Query(value="from ContractProduct where contract.id i...
  • qq_41507845
  • qq_41507845
  • 2018年01月06日 19:50
  • 19

Java EE中Ajax技术简单实现

1.异步数据获取技术,使用XMLHttpRequest.   2.基于标准的表示技术,使用XHTML与CSS.   3.动态显示和交互技术,使用Document Object Model(文档对象模型...
  • suwu150
  • suwu150
  • 2016年05月18日 12:42
  • 846

Java EE服务端学习(1)

一言不合就翻译官方文档。。。话说这文档翻译的也挺辛苦,转载请说明出处!! 什么是RESTful Web服务? RESTful Web服务是松散耦合的轻量级的web服务,特别是适用于为在网络上传播的...
  • majalis_C
  • majalis_C
  • 2016年11月24日 21:18
  • 436

JPA学习笔记(12)——JPQL

Query接口int executeUpdate()用于执行update或delete语句。List getResultList()用于执行select语句并返回结果集实体列表。Object getS...
  • u010837612
  • u010837612
  • 2015年08月20日 17:01
  • 2224

eclipse Java EE平台使用指南(二)

3.5创建servlet 3.6快速访问方法的声明与实现(3.5提供) 3.7 修改项目发布工程名(虚拟子目录) 3.8 发布web 项目 3.8.1 发布环境分类 ...
  • rachel_luo
  • rachel_luo
  • 2013年05月20日 13:44
  • 1347
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在 Java EE应用程序中使用JPQL
举报原因:
原因补充:

(最多只允许输入30个字)