示例应用程序
本文讨论的代码段摘自本文随附的示例应用程序中使用的 Java 源文件。浏览一下示例存档,您可能会注意到,这是一个基于 Java Servlet 和 Java 持久性 API 技术的简单 Web 应用程序。为简单起见,它不使用企业 bean,而是直接从 servlet 内部发出 JPQL 查询。但是,这并不意味着您将不能在企业 bean 中利用这里讨论的 JPQL 查询 — 您可以在任何 Java EE 组件中定义 JPQL 查询。
图 1 显示了示例实体结构。如您所见,它包含一组通过不同类型的关系彼此关联的实体。为了说明本文后面的“定义 JPQL 联接”部分中讨论的 JPQL 连接查询的用法,需要这样一个分支结构。
图 1 示例应用程序中使用的实体之间的关系
图 1 示例应用程序中使用的实体之间的关系
要详细了解如何设置和启动示例应用程序,可以参考示例存档根目录下的 readme.txt 文件。
在 Java EE 应用程序中使用 JPQL
如果您使用过数据库,您很可能已经使用过 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 的相应方法,执行以下一般步骤:
使用注入或通过 EntityManagerFactory 实例显式获取一个 EntityManager 实例。
通过调用相应 EntityManager 的方法(如 createQuery),创建一个 Query 实例。
如果有查询参数,使用相应 Query 的 setParameter 方法进行设置。
如果需要,使用 setMaxResults 和/或 setFirstResult Query 的方法设置要检索的实例的最大数量和/或指定检索的起始实例位置。
如果需要,使用 setHint Query 的方法设置供应商特定的提示。
如果需要,使用 setFlushMode Query 的方法设置查询执行的刷新模式,覆盖实体管理器的刷新模式。
使用相应 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 arr_cust = (List)em.createQuery("SELECT c FROM Customer c")
.getResultList();
out.println("List of all customers: "+"
");
Iterator i = arr_cust.iterator();
Customer cust;
while (i.hasNext()) {
cust = (Customer) i.next();
out.println(cust.getCust_id()+"
");
out.println(cust.getCust_name()+"
");
out.println(cust.getEmail()+"
");
out.println(cust.getPhone()+"
");
out.println("----------------" + "
");
}
...
当然,这里让人关注的是 EntityManager 实例的 createQuery 方法和 Query 实例的 getResultList 方法。EntityManager 的 createQuery 用于创建 Query 实例,然后该实例的 getResultList 方法用于执行作为参数传递给 createQuery 的 JPQL 查询。正如您可能已经猜