在 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 联接查询的示例,该查询的选择列表由源自多个实体的字段组成。

相关文章推荐

Java EE 7 教程 第一部分 简介 第2章 使用教程示例 第2.9节 调试Java EE应用程序

本节将介绍如何确定是什么原因造成应用程序部署或执行错误.

arcgis api for flex之四、使用BlazeDS与Flash Builder4.5整合Java EE应用

前言 写这篇文章的目的是对于一个完全不懂的新手,也能快速step by step创建Flex与Java EE的整合应用,开启java与flex的企业级应用开发的第一页。 开发环境及工具 windo...

使用BlazeDS与Flash Builder4.5整合Java EE应用(一)

前言 写这篇文章的目的是对于一个完全不懂的新手,也能快速step by step创建Flex与Java EE的整合应用,开启java与flex的企业级应用开发的第一页。 开发环境及工具 ...

使用MyEclipse开发Java EE应用:如何配置一个独立的Java项目

买MyEclipse送Java畅销书,仅限15天!!活动火热开启中>> 【MyEclipse最新版下载】 有时可能您已经有EJB项目和其他Java项目组成的EJB应用程序。 请注意,如...

面向Flex/Java EE应用的全新企业平台

本文来源于我在InfoQ中文站翻译的文章,原文地址是:http://www.infoq.com/cn/news/2011/07/graniteds-ep上周,Granite Data Services...

轻量级Java EE应用相关技术

轻量级Java EE应用以传统的JSP作为表现层技术,以一系列开源框架作为MVC层,中间层,持久层解决方案,并将这些开源框架有机的组合在一起,使得Java EE应用具有高度的可扩展性,可维护性。 一...

【S2HS学习笔记】第一章节:Java EE应用和开发环境

1. Java EE应用的分层模型   1.1. Java EE架构模式大致可以分为以下几层:    >> Domain Object(领域对象)层:此层由POJO(Plain Old Java Ob...

经典Java EE应用和开发环境

  • 2015年12月14日 20:41
  • 4.88MB
  • 下载

《Java EE应用开发及实训》

  • 2013年03月31日 13:01
  • 5.22MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在 Java EE应用程序中使用JPQL
举报原因:
原因补充:

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