通过 WebSphere Application Server V6.1 利用 OpenJPA

针对 JPA 2.0 更新

Apache OpenJPA 项目是 Java™ Persistence API 的一个开放源代码实现,旨在构建一个稳健、高性能、可伸缩的 JPA 规范实现。本文通过一个完整的示例来介绍 OpenJPA,该示例演示了如何通过 IBM® WebSphere® Application Server V6.1 来利用 OpenJPA 的部分功能。 针对 JPA 2.0 更新。 本文来自于 IBM WebSphere Developer Technical Journal

Kevin Sutter, 高级软件工程师, IBM India Software Lab Services and Solutions

Kevin Sutter 是 WebSphere Application Server 开发部的一名高级软件工程师。他目前负责 WebSphere 的 Java Persistence API 实现。Kevin 过去担任过的职务包括领导和设计 J2EE Connector Architecture (JCA) 和 ObjectGrid(缓存框架)的 WebSphere 解决方案。



2011 年 11 月 28 日 (最初于 2006 年 12 月 06 日)

简介

EJB 3.0 规范对 EJB 编程模型进行了重大的(有人说是必要的)改造。整个 EJB 编程模型集中于带注释的普通 Java 对象(plain old Java object,POJO)的使用,与过去的 EJB 规范具有根本性的区别。这个新编程模型得到大量关注的一个方面是持久性体系结构。本文通过一个完整的示例来介绍这个新的 Java Persistence API,该示例演示了如何通过 WebSphere Application Server V6.1 来利用该 API 的部分功能。

本文侧重于介绍在没有 EJB 3.0 特性包的情况下 OpenJPA 在 WebSphere Application Server V6.1 中的使用。没有对 EJB 3.0 Feature Pack 进行更新来支持 JPA 2.0 规范,但是如果您觉得本文所介绍的 JPA 集成限制是可接受的,那么通过 WebSphere Application Server V6.1 使用 OpenJPA 2.x 也是可行的。

本文在下列软件基础上进行了更新:

  • WebSphere Application Server V6.1.0.35
  • Application Server Toolkit V6.1.1.9
  • Apache OpenJPA V2.0.1

JPA 简述

Java Persistence API (JPA) 是 Java EE 5 EJB 3.0 (EJB 3) 系列规范的组成部分。EJB 3 专家组提出了三个规范:

  • EJB Core Contracts and Requirements
  • EJB 3.0 Simplified API
  • Java Persistence API 1.0.

2007 年 7 月 JPA 2.0 被提议成为规范 JSR-317。它依然是 Java EE 6 系列规范之一,但不再是 EJB 规范。

JPA 规范定义持久性的管理和与 Java EE 及 Java SE 环境的对象/关系映射。

简而言之,JPA 规范涵盖以下关键领域:

  • 引入了一个新的基于 POJO 的编程模型,它同样适用于 Java EE 和 Java SE 环境。除了使用基于 XML 的机制外,现在还可以使用注释来直接在应用程序中定义元数据。此外,实体 POJO 不再需要实现任何基于 EJB 框架的接口。

    • 该编程模型还定义了 POJO(实体)对象的分离模型。这对于客户机/服务器和 Web 应用程序环境应该是一个优点。
    • 除了增强 EJB 查询语言(EJB Query Language,也称为 JPQL)外,该编程模型还支持使用本机 SQL 查询。
  • 该 JPA 规范还明确定义了对象/关系 (O/R) 映射,而不是依赖以前版本中特定于供应商的 O/R 映射。这应该有助于更换供应商和迁移应用程序。

  • 一些与持久性相关的其他项也进行了标准化:

    • 用于开放式并发控制的对象版本控制
    • 数据库键生成
    • 字段的惰性与积极加载
    • 继承
  • JPA 2.0 引入了:

    • 附加的 O/R 映射增强使其成为一个更完备的解决方案。
    • 一个标准化的悲观锁(pessimistic lock)管理器。
    • 可对 JPA 提供商的二级缓存进行访问,如果缓存可用的话。
    • 一个可通过 Metamodel 和 Criteria API 查询功能的编程接口。
    • 集成 Bean Validation (JSR 303)。

所有这一切简化付出了一定的代价。由于编程模型的重大变化,现有 EJB 2.x 应用程序将需要重新编写才能利用新的 JPA 功能。此外,新的 JPA 规范没有包括容器管理关系(container-managed relationship,CMR)的自动维护。关系维护现在是应用程序管理的。

有关 Java Persistence API 的更多详细信息,可以在Java Community Process 网站 以及在若干白皮书、文章、演示文稿和图书中找到(见 参考资料)。


OpenJPA 简介

Apache OpenJPA 项目是一个 Apache 授权的开放源代码 Java Persistence API 实现。OpenJPA 旨在构建一个稳健、高性能、可伸缩的 JPA 规范实现。

由于业界对此 OpenJPA 项目的兴趣,本文将帮助解释如何立即在您的 WebSphere Application Server 环境中利用此实现。

本文同样适用于 JPA 1.0 和 JPA 2.0 标准。概念、样例、解释和屏幕截图通用,与所使用的具体 OpenJPA 版本无关。


样例应用程序研究

在我们的示例中,我们将使用一个客户订单系统 (Customer Order System),客户在其中创建订单、添加产品项,然后提交订单。图 1 演示了样例系统中的用例。

图 1. 样例应用程序用例
图 1. 样例应用程序用例

图 2 中的活动图演示了那些用例的执行顺序。

图 2. 样例应用程序用例顺序
图 2. 样例应用程序用例顺序

在此示例中,我们仅关注 Persistence 层,因为我们的目标是说明如何在 WebSphere Application Server V6.1 中使用 OpenJPA 作为持久层。

图 3. 数据库数据模型
图 3. 数据库数据模型

我们的样例数据库中有 4 个表:

  • CUSTOMER:
  • ORDER:
  • LINEITEM:
  • PRODUCT:

在我们的示例应用程序中,我们有 4 个对应的 JPA 实体,如图 4 中的类图所示。

图 4. 类图
图 4. 类图

这里要注意两个关于映射的要点:

  • Customer 实体具有到 CustomerOrder 的单向一对一关系,而 Order 则具有返回到 Customer 的单向多对一关系。这不是双向关系的原因在于,Customer 仅维护当前打开订单的一个实例。然而,Order 表则具有该客户的所有订单,而不管订单的状态如何。由于我们拥有单向关系,这将影响您设置关系的方式,因为每一方都必须设置。

  • CustomerOrder 和 Line Item 具有双向(因此也是受管理的)关系。

我们使用 EJB 会话 Facade 层来表示用例。由于 WebSphere Application Server V6.1 支持 EJB 2.1,我们将使用 EJB 2.1 会话 Bean。然而,考虑到将来对 EJB 3 的支持,我们将所有的 Facade 逻辑转移到一个 POJO 中。这样,当您转向 EJB 3 会话 Bean 时,您所需做的就是删除 EJB 2.1 会话 Bean 层,并对 POJO 进行注释。图 5 是该会话 Bean 和对应的 POJO 的类图。

图 5. 会话 bean 和 POJO 类图
图 5. 会话 bean 和 POJO 类图

为了演示流,该序列图演示了 Find Customer 用例的实现。所有的 Facade 逻辑都是在 OrderProcessor POJO 中执行的。Order Processor 与 JPA 实体管理器和 JPA POJO 交互以完成其持久性代码。EJB 2.1 会话 Bean 委托给 POJO。稍后您可以查看该代码。

图 6. 序列图
图 6. 序列图

类似地,图 7 显示了 Open Order 实现。所有的用例都遵循这个基本的 EJB 2.1 会话 Bean 流,即调用一个 Facade POJO,后者又与 JPA 实体管理器交互。

图 7. Open Order 实现
图 7. Open Order 实现

使用 Application Server Toolkit 来设置 JPA 开发环境

若要运行此示例,您需要 下载本文附带材料

访问 OpenJPA 构建

由于本文所介绍的 OpenJPA 使用针对一个应用程序管理的持久化环境,您可以使用下列任何 OpenJPA 版本:

  • OpenJPA v1.0.4(最新版本,相当于 WebSphere Application Server V6.1 Feature Pack for EJB 3.0)
  • OpenJPA v1.2.2(最新版本,相当于 WebSphere Application Server V7.0)
  • OpenJPA v2.0.1(最新版本,相当于 WebSphere Application Server V7.0 Feature Pack for OSGi Applications and JPA 2.0)

您可以通过 下载 openjpa-0.9.6-incubating.zip 文件 来访问 OpenJPA 2.0.1 构建。有关下载 OpenJPA 的其他方法的更多详细信息,请参见 参考资料

您可以将该下载文件解压缩到任何位置。该 ZIP 文件的根目录包含 OpenJPA 实现 JAR 文件,如图 8 所示

图 8. OpenJPA 实现 JAR 文件
图 8. OpenJPA 实现 JAR 文件

(OpenJPA 2.x 版本引入了一个 “总” JAR 文件(如 openjpa-all-2.0.1.jar),在一个易于使用的 JAR 文件中包含所有必需的依赖项。然而,为了使本文可适用于任何 OpenJPA 版本,依赖项将分开处理。)

在 lib 目录下面,您将找到所需的依赖项。

图 9. JAR 依赖项
图 9. JAR 依赖项

稍后我们将介绍如何在 EAR 中对这些 JAR 文件打包。

设置工作区

WebSphere Application Server V6.1 附带了 Application Server Toolkit (AST) V6.1。AST 是 Eclipse Web Tools 项目的超集,其中添加了特定于 WebSphere Application Server 的功能,例如 WebSphere Application Server 测试服务器。在本部分中,您将了解如何设置 AST 以实现无缝的 OpenJPA 开发。

  1. 启动 Application Server Toolkit:

    1. 打开一个空的工作区。

      图 10. 启动工作区
      图 10. 启动工作区
    2. 关闭欢迎屏幕。

      图 11. AST 欢迎屏幕
      图 11. AST 欢迎屏幕
    3. 切换到 J2EE 视图。

      图 12. 选择 J2EE 视图
      图 12. 选择 J2EE 视图
  2. 您必须做的第一件事情是将 WebSphere Application Server V6.1 设置为一个单元测试环境。我们假设您已经准备好一个本地单服务器 WebSphere Application Server V6.1 安装。我们还假设您已经创建了一个概要文件。(有关安装和概要文件的更多信息,参见参考资料。)

    1. 转到 Servers 视图并在该视图中右键单击。

    2. 选择 New => Server(如图 13 所示)。

      图 13. 创建新服务器
      图 13. 创建新服务器
    3. 选择 IBM=>WebSphere v6.1 ServerCreate New runtime,然后按 Next(如图 14 所示)。

      图 14. 创建新的运行时
      图 14. 创建新的运行时
    4. 保留 Name 的默认值,并指向 WebSphere Application Server V6.1 的安装目录。按 Next

      图 15. 定义新的运行时
      图 15. 定义新的运行时
    5. 选择一个具有适当 SOAP 端口号的应用程序服务器概要文件。在我们的示例中,我们使用了一个受保护的概要文件。按 Finish

      图 16. 定义新服务器
      图 16. 定义新服务器
  3. 您的 AST 可能默认设置为使用 Java 1.4 JDK 和 JRE。您需要更新首选项才能编译 Java 5 代码,因为 JPA 依赖 Java 5 注释和功能。

    1. 在主菜单窗口选择 Window,然后选择 Preferences

      图 17. 更改首选项
      图 17. 更改首选项
    2. 展开 Java 并选择 Compiler

    3. 将 Compiler compliance level 切换到 5.0,然后单击 Apply

      图 18. 更改编译器遵从性级别
      图 18. 更改编译器遵从性级别
    4. 切换到 Installed JREs 并选择 WebSphere Application Server v6.1 JRE

      图 19. 切换 JRE
      图 19. 切换 JRE
    5. 单击 OK 保存更改,然后单击 Yes 来进行构建。

      图 20. 更改编译器设置和构建
      图 20. 更改编译器设置和构建

创建一个 Java EE 项目

在本部分中,我们将简单介绍如何创建各种 Java EE 项目和设置 EAR 文件以包含 JPA。

  1. 若要创建一个 Enterprise Application Project 及其对应的子项目(一个 EJB 项目和 Web 项目),在 Project Explorer 中右键单击 Enterprise Applications 并选择 New => Enterprise Application Project

    图 21. 创建 Enterprise Application Project
    图 21. 创建 Enterprise Application Project
  2. 对于 Project Name,请输入 OpenJPATestEAR,对于 Target runtime,请选择 WebSphere Application Server v6.1(参见图 22)。要注意,不要一不小心选择中 WebSphere Application Server v6.1 stub。保留 Configurations 为 <custom>。单击 Next

    图 22. 定义 Enterprise Application Project
    图 22. 定义 Enterprise Application Project
  3. 接受 Select Project Facets 页上的默认设置并单击 Next(参见图 23)。

    图 23. Select Project Facets
    图 23. Select Project Facets
  4. 在 J2EE Modules 上添加 EAR 面板,确保 Content Directory 被设置为 EarContent。按 New Module... 来启动 New J2EE Module 向导(如图 24 所示)。

    图 24. 启动 New J2EE Module 向导
    图 24. 启动 New J2EE Module 向导
  5. 使用以下名称分别创建一个 EJB 项目和一个 Web 项目(见图 25):

    • EJB 模块:OpenJPATest
    • Web 模块:OpenJPATestWeb

    单击 Finish

    图 25. 创建默认 J2EE 模块
    图 25. 创建默认 J2EE 模块
  6. 您刚才创建的模块将在项目窗口中列出。单击 Finish 以完成 EAR 项目的创建(参见图 26)。

    图 26. EAR 项目创建完成
    图 26. EAR 项目创建完成

要注意的是,在创建所有必要的构件和导入所需的依赖项之前,您将遇到一些编译错误。

设置 DB2 数据库和 WebSphere Application Server 数据库配置

若要运行该应用程序,您必须设置数据库。在我们的示例中,我们使用了 DB2® Version 9,并且同时提供了一个表 DDL 脚本和测试数据。根据您所使用的数据库,可能需要修改数据库模式。(或者,您也可以使用 OpenJPA 文档来为您的数据库生成 DDL。有关更多信息,参见 参考资料。)

  1. 在所提供的 下载文件 的 OrderEntryDB 文件夹中找到您将需要的脚本。

  2. 使用 DB2 命令窗口来运行这些脚本。若要访问 DB2 命令窗口,导航到 IBM DB2 => Command Line Tools => Command Window

    1. 通过输入如下 DB2 命令来创建一个 DB2 数据库:

      db2 create db JPATEST

    2. 当该数据库创建完成时,使用如下命令从同一个命令窗口连接到该数据库:

      db2 connect to JPATEST user db2admin using db2admin

    3. 通过发出如下命令来运行下载文件中包括的 DDL 脚本:

      db2 –tvf C:\<directory>\createTables.DDL

    4. 您可以通过类似方式来运行数据创建脚本:

      db2 –tvf C:\<directory>\createData.sql

  3. 为简化此示例,我们使用了 WebSphere Application Server 中一个称为增强 EAR 的功能。该功能允许您在应用程序中存储数据库配置。在应用程序安装时,WebSphere Application Server 将使用此信息来创建适当的配置。这将在配置应用程序服务器所需的 JDBC 驱动程序和数据源时节省时间。

    (务必记住,增强 EAR 功能用于快速原型化,但它是在服务器上使用 wsadmin 脚本(或管理控制台)来配置所需资源的最佳实践,以便能够在各种测试环境和生产环境中正确地管理应用程序。)

    1. 若要将数据库配置添加到应用程序,请打开 EAR 项目中的 application.xml 文件。这可以通过双击 OpenJPATestEAR 部署描述符图标来实现,如图 27 所示。

      图 27. 打开 EAR 项目
      图 27. 打开 EAR 项目
    2. 选择 Deployment 选项卡。图 28 突出显示了我们感兴趣的配置项。

      图 28. 部署描述符配置
      图 28. 部署描述符配置

      点击查看大图

      图 28. 部署描述符配置

      图 28. 部署描述符配置
    3. 可以看到,配置面板中存在多个部分。若要输入值,请单击 Add 来启动针对某个特定配置项的向导。下面是您将为每个部分输入或选择的值的摘要。完成这个配置面板后,记得保存 Application Deployment 描述符。

      JDBC Driver:

      • 屏幕 1:
        • Database 类型:IBM DB2
        • JDBC 提供类型:DB2 Universal JDBC Provider (XA)
          (请确保使用 Type 4 Universal Driver,它使用所需的 JDBC 3.0 API)
      • 屏幕 2: :
        • 名称:DB2XA
        • 实现类名:com.ibm.db2.jcc.DB2XADataSource
        • 接受默认的 Class 路径和 Native 路径

      DataSource:

      • 屏幕 1:
        • 提供商类型:DB2 Universal JDBC Driver Provider (XA)
        • Version 5.0 数据源
      • 屏幕 2:
        • 名称:OrderDS
        • JNDI 名:jdbc/orderds
        • 容器管理的身份认证别名:DBUser
      • 屏幕 3:
        • 数据库名:JPATEST
        • 服务器名:localhost

      身份认证别名:

      • 别名:DBUser
      • 用户 id:<<database id>>
      • 密码:<<password>>

      替代变量:

      • DB2UNIVERSAL_JDBC_DRIVER_PATH: <<DB2 Root>>/java
      • 示例:C:\Progra~1\IBM\SQLLIB\java

将 JPA JAR 文件添加到企业应用程序

您需要将 OpenJPA JAR 和依赖项添加到 EAR 文件,具体方法是将它们导入 Enterprise Application Project 的 EarContent 文件:

  1. 首先,添加依赖 JAR 文件:

    1. 右键单击 OpenJPATestEAR 项目下面的 EarContent 文件夹并选择 Import...,如下所示。

      图 29. 导入 JAR 文件
      图 29. 导入 JAR 文件
    2. 选择 File system,然后单击 Next(如图 30 所示)。

      图 30. 选择文件系统
      图 30. 选择文件系统
    3. 在 From directory 字段中,导航到您下载 JPA 的目录,然后导航到该目录中的 lib 目录。选择以下 JAR 文件(参见图 31):

      • common-collections-3.2.1.jar
      • common-lang-2.1.jar
      • commons-pool-1.5.3.jar
      • geronimo-jpa_2.0_spec-1.1.jar
      • serp-1.13.1.jar

      (类似 JAR 文件,稍有不同的是如果您使用另一个 OpenJPA 版本,需要选中版本名称。不需要其他依赖 JAR 文件,因为 WebSphere Application Server 提供了所需的 J2EE JAR 以及常用的日志记录功能。此外,由于此示例使用 DB2,因此也不需要 Derby 运行时 JAR。)

      单击 Finish

      图 31. 选择要导入的 JAR 文件
      图 31. 选择要导入的 JAR 文件
  2. 下一步需要导入 JPA 实现 JAR 文件。右键单击 OpenJPATestEAR 项目下的 EarContent 文件夹然后选择 Import...。与前面一样,指向 JPA 安装目录的根目录,并选择以下要导入的 jar:openjpa-2.0.1.jar,然后单击 Finish

    图 32. 导入 JPA 实现 JAR 文件
    图 32. 导入 JPA 实现 JAR 文件
  3. 下一步,更新 EJB 项目类路径,以便它能够找到 JAR 文件:

    1. 在 EJB Projects 文件夹下面,右键单击 OpenJPATest 项目并选择 Properties(参见图 33)。

      图 33. 打开项目属性
      图 33. 打开项目属性
    2. 将输出目录更改为与源目录相同。这将确保 JPA Enhancement 步骤能够正确工作。为此,请选择 Java Build Path 项,并将 Default Output Folder 更改为 OpenJPATest/ejbModule(参见图 34)。

      图 34. 使输出目录和源目录相同
      图 34. 使输出目录和源目录相同
    3. 切换到 J2EE Module Dependencies 并选择所有 JARs,如图 35 所示。

      图 35. 选择所有依赖 JAR 文件
      图 35. 选择所有依赖 JAR 文件
  4. 现在您可以导入项目的 Java 源代码了。

    1. 右键单击 OpenJPATest Project 下面的 ejbModule 文件夹,并选择 Import

    2. 选择 File system,然后单击 Next

    3. 假设您已经将下载资料展开到某个目录中,请输入下载目录下的 ejbModule 文件夹(参见图 36)。

      图 36. 导入下载的资源
      图 36. 导入下载的资源
    4. 在请求覆盖许可时,请选择 Yes To All

设置 Eclipse 构建以包括增强

OpenJPA 依赖字节代码增强来向 JPA 对象添加持久性行为。增强某个类的方法有多种(参见 参考资料)。在我们的示例中,我们提供了一个简单的 ANT 脚本来运行增强程序。为了使开发过程更简单,您将把 Ant 构建整合为 Eclipse 构建的一部分。这样,当您在 Eclipse 中编译类时,JPA 增强程序将作为该构建的一部分来运行。这将简化您的开发过程。

  1. ANT 脚本是一个非常简单的脚本,它利用了 OpenJPA 增强程序工具。打开位于 ejbModule 目录的根目录中的 build.xml 文件。该 ANT 文件指向实体包以及 persistence.xml 文件。(我们将在接下来的部分研究该文件。)

    图 37. 打开 build.xml 文件
    图 37. 打开 build.xml 文件
    清单 1
    <project name="enhanceJPA">
    <target name="enhance">
      <!-- define the openjpac task; this can be done at the top of the    -->
      <!-- build.xml file, so it will be available for all targets      -->
      <taskdef name="openjpac"
    classname="org.apache.openjpa.ant.PCEnhancerTask"/>
    
      <openjpac>
      	<config propertiesFile="./META-INF/persistence.xml"/>
        <fileset dir=".">
        <include name="**/com/ibm/persistence/ejb3/order/entity/*.java" />
        </fileset>
        <classpath>
          <pathelement location=”${basedir}” />
        </classpath>
      </openjpac>
    </target>
    
    </project>
  2. 若要作为 Eclipse 构建的一部分来运行该增强程序,您需要配置一个生成器:

    1. 右键单击 OpenJPATest EJB 项目并选择 Properties

      图 38. 打开项目属性
      图 38. 打开项目属性
    2. Builders 部分,单击 New 并选择 Ant Build(参见图 39)。

      图 39. 配置 Ant 构建
      图 39. 配置 Ant 构建
    3. 将构建器命名为 JPAEnhance.

    4. Main 选项卡之下,浏览该工作区并选择 ejbModule 目录下面的 build.xml 文件。

    5. 在 Base Directory 部分。浏览工作区并选择 ejbModule 目录。

    6. Arguments 部分,添加 "-verbose -debug" 标志。最后的配置应该与图 40 类似。

      图 40. 配置构建器
      图 40. 配置构建器
    7. Refresh 选项卡下面选择 Refresh resources upon completion 以在完成增强后刷新整个工作区(参见图 40)。

      图 41. 在完成时刷新工作区
      图 41. 在完成时刷新工作区
    8. 切换到 Targets 选项卡,并在 Clean、Manual Build 和 Auto Build 中选择 enhance 任务(参见图 41)。

      图 42. 选择增强任务
      图 42. 选择增强任务
    9. 在 Classpath 选项卡下面(参见图 43),通过单击 Add Jar 来添加所有 JPA JAR,通过浏览工作区并选择 EAR 文件来添加所有 EAR 内容。

    10. 最后,添加 WebSphere Application Server 安装的 lib 目录中的 j2ee.jar 文件。这可以通过选择 Add external JARs... 来完成。

      图 43. 将 JAR 文件添加到配置
      图 43. 将 JAR 文件添加到配置
    11. OK 来保存构建器。

    12. JPAEnhance 任务应该是您的构建中完成的最后一个任务(参见图 44)。如果有自动构建,则您的增强程序应该会运行(参见图 45)。图 46 显示了成功的增强运行所产生的输出示例。

      图 44. 构建任务
      图 44. 构建任务
      图 45. 激活自动构建
      图 45. 激活自动构建
      图 46. 成功的增强运行所产生的输出
      图 46. 成功的增强运行所产生的输出

检查示例应用程序

现在我们已经配置了数据库、服务器配置和工作区,下面让我们检查一下该应用程序。我们已经提供了体系结构概述,因此我们将仅强调打包并研究 OpenJPA 配置。

  1. 使用 Project Explorer,展开 ejbModule 文件夹以查看所有的包。图 47 总结了包的位置。

    1. JPA 实体包包含带注释的 JPA 实体对象。

      图 47. 所有 ejbModule 包
      图 47. 所有 ejbModule 包
    2. 检查实体。清单 2 显示了 Customer Entity 对象。通过添加注释,您可以使实体对象启用持久性,如下面的类所示。

      清单 2
      package com.ibm.persistence.ejb3.order.entity;
      
      import java.io.Serializable;
      import javax.persistence.*;
      
      @Entity
      @Table(name="CUSTOMER", schema="CUSTSCH")
      public class Customer implements Serializable {
      
      	
      	private Integer id;
      	private String name;
      	private CustomerOrder currentOrder;
      		
      	@Id
      	@Column(name="CUST_ID")
      	public Integer getId() {
      		return id;
      	}
      	public void setId(Integer id) {
      		this.id = id;
      	}
      	
      	@Column(name="NAME")
      	public String getName() {
      		return name;
      	}
      	public void setName(String name) {
      		this.name = name;
      	}
      	
      	
      	 @OneToOne(fetch=FetchType.EAGER,cascade = 
      {CascadeType.MERGE,CascadeType.REFRESH},optional=true )
      	 @JoinColumn(name="OPEN_ORDER_ID",referencedColumnName="
      ORDER_ID") 
      	public CustomerOrder getCurrentOrder() {
      		return currentOrder;
      	}
      	public void setCurrentOrder(CustomerOrder currentOrder) {
      		this.currentOrder = currentOrder;
      	}
      
      }
    3. 此外,您还可以看到包含 OrderProcessorBean 的 POJO Facade 包。该包使用 JPA 来访问和更新实体。清单 3 显示了部分 OrderProcessorBean。请注意,在构造函数中,我们查找了两个 EntityManagerFactory。我们将在接下来的部分中了解这样做的原因。

      清单 3
      public class OrderProcessorBean implements OrderProcessor {
      
      	private EntityManagerFactory emf;
      	
      	private EntityManagerFactory emfPessLock;
      	
      	public OrderProcessorBean() {
      		emf = 
      EntityManagerFactoryHelper.getEntityManagerFactory("OrderDB");
      		emfPessLock = 
      EntityManagerFactoryHelper.getEntityManagerFactory("OrderDBPessLock");
      	}
      
      	public Customer findCustomerById(int customerId) throws 
      CustomerDoesNotExist{
      		//1. Finds customers by ID.
          EntityManager em = null;
          try {  
      	em = emf.createEntityManager();
      	Customer customer =   findCustomerByIdInternal(customerId,em);
      	return customer;
          } finally {
            if (em != null) {
              em.close();
            }
          }
      }

      (我们使用应用程序管理的实体管理器。这意味着我们无法将该实体管理器注入调用代码。相反,我们必须自己加载 EntityManagerFactory。此外,您必须在加载完成时关闭 EntityManager。我们将在接下来的部分中介绍这一主题。)

  2. persistence.xml 是定义持久性单元的描述符,其中包含 JPA 实体和数据库所需的配置。

    1. 打开 persistence.xml 并检查其内容。

      图 48. 打开 persistence.xml
      图 48. 打开 persistence.xml
    2. 清单 4 显示了 persistence.xml。请注意,存在两个不同的持久性单元。前面,我们提到 OrderProcessor 类使用了两个 EntityMangerFactory。由于我们同时拥有读取和写入访问模式,我们需要为每种类型定义一个模式,一个针对乐观读取,另一个针对悲观更新。其中还定义了几个属性:

      • JPA 提供商:在此例中是 OpenJPA。
      • jta-data-source:在此例中,它是在调用会话 Bean 上定义的一个资源引用。
      • TransactionMode:管理的;这使得 OpenJPA 能够将事务委托给基础 EJB 容器。
      • ConnectionFactoryMode:管理的:这使得应用程序服务器能够管理连接访问。
      • DBDictionary property:支持正确转换到 DB2 查询。如果您在使用其他数据库,则需要将其调整为正确的值(请参见 参考资料 中的 OpenJPA 文档以了解受支持的数据库)。
      • LockManager property:在第二个持久单元上,这将锁设置为悲观的,例如,使 OpenJPA 能够在适当的时候使用 “Select For Update”。
      • Log property:已注释,但是可用于帮助调试潜在 OpenJPA 使用问题。
      清单 4
      <persistence 
      	xmlns="http://java.sun.com/xml/ns/persistence"
      	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
      		http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
      	version="1.0">
      <persistence-unit name="OrderDB">
      	<provider>
      		org.apache.openjpa.persistence.PersistenceProviderImpl
      		</provider>
      		<jta-data-source>
      			java:comp/env/jdbc/orderds
      		</jta-data-source>
      		<properties>
      		<property name="openjpa.TransactionMode" 
      			value="managed"/>
      		<property name="openjpa.ConnectionFactoryMode" 
      			value="managed"/>
          		<property name="openjpa.jdbc.DBDictionary" 
      			value="db2"/>
                  <!-- <property name=”openjpa.Log”
                      value=”Default=TRACE”/>  -->
      	</properties>
      	</persistence-unit>
      	<persistence-unit name="OrderDBPessLock">
      	<provider>
      	org.apache.openjpa.persistence.PersistenceProviderImpl
      	</provider>
      	<jta-data-source>java:comp/env/jdbc/orderds</jta-data-source>
      	<properties>
      	<property name="openjpa.TransactionMode" 
      		value="managed"/>
      	<property name="openjpa.ConnectionFactoryMode" 
      		value="managed"/>
          	<property name="openjpa.jdbc.DBDictionary" 
      		value="db2"/>
      	<property name="openjpa.LockManager"
      		value="pessimistic(VersionCheckOnReadLock=true,VersionUpdate
      		OnWriteLock=true)"/>
                  <!-- <property name=”openjpa.Log”
                      value=”Default=TRACE”/>  -->
      	</properties>
      </persistence-unit>
      </persistence>

存在两种 EM 配置类型:

  • JTA-configured 类型侦听直接来自事务服务的事务事件(开始/提交/回滚)。
  • Resource-Local 类型通过调用 EntityTransaction 接口的应用程序来了解这些事件。

在 WebSphere Application Server V6.1 中运行 Open JPA 将支持通过上述配置来处理 JTA 事务。然而,JPA 定义了容器管理的实体管理器与应用程序管理的实体管理器的概念。若要了解它们之间的区别,您必须首先了解持久性上下文的含义。

持久性上下文是一组托管实体实例,其中对于任何持久实体标识,都存在一个唯一的实体实例。在持久性上下文中,实体与基础持久性存储区的关联由实体管理器(entity manager,EM)管理。

容器管理的 EM 实例是通过指示容器注入一个实例(通过直接注入或通过注入式 JNDI 查找)来创建的;该 EM 实例的生存期由容器控制;该实例的生存期与它所注入到的组件的生存期相匹配。对于每个容器管理的 EM 实例,都存在一个或多个对应的容器管理的持久性上下文(Persistence Contexts,PC)。在创建 PC 时,它与当前有效的事务相连,并连同事务上下文一起由容器传播到相同 JVM 中的其他被调用组件。容器管理的使用场景又进一步细分为事务范围的(生存期由事务控制)和扩展的(生存期由一个或多个有状态会话 Bean 实例来控制)。

应用程序管理的 EM 实例是通过调用 EntityManagerFactory(可以对它本身进行注入或在 JNDI 中进行查找)来创建的,并且该实例的生存期由应用程序控制。对于每个应用程序管理的 EM 实例,都存在一个或多个对应的应用程序管理的持久性上下文,此上下文不与任何事务相连(隔离的),并且不传播到其他组件。这并不意味着不能将应用程序管理的实体管理器配置为 JTA 实体管理器。然而,务必要认识到您必须自己打开和关闭该实体管理器。

容器管理的实体管理器和应用程序管理的实体管理器(及其持久性上下文)都要求在 Java EE Version 5 Web 容器和 EJB 容器中受到支持。在 EJB 环境中,通常使用容器管理的实体管理器。当将 OpenJPA 与 WebSphere Application Server V6.1 一起使用时,只有应用程序管理的实体管理器才受支持。然而,如前所述,仍然可以使用 JTA 来配置应用程序管理的实体管理器。预计 WebSphere Application Server 的将来版本将支持容器管理的实体管理器。正确的代码分层应该有助于在转向 EJB 3 时转向容器管理的实体管理器。

导入 Web 客户端

为了测试我们的应用程序,我们提供了一个简单的测试 Servlet,它以所需的顺序执行我们的用例。

  1. 首先,您必须导入那些 Web 构件:

    1. 右键单击 OpenJPATestWeb 项目并选择 Import(图 49)。

      图 49. 导入 Web 构件
      图 49. 导入 Web 构件
    2. 选择 File System,然后单击 Next

    3. 在 From directory 字段中,浏览到 <<download materials>>/WebClient(参见图 50)。确保 Into 文件夹是该 Web 项目的根目录。单击 Finish

      图 50. 浏览下载的 Web 客户端
      图 50. 浏览下载的 Web 客户端
    4. 单击 Yes to All 覆盖默认设置。

      图 51. 覆盖默认设置
      图 51. 覆盖默认设置
  2. 下一步,您需要更新该 Web 项目的类路径以指向 EJB JAR 文件。

    1. 右键单击该 Web 项目并选择 Properties(参见图 52)。

      图 52. 更新项目属性
      图 52. 更新项目属性
    2. 在 J2EE Module Dependencies 下面,选择 OpenJPATest.jar 文件并单击 OK(图 53)。

      图 53. 选择 JAR 文件
      图 53. 选择 JAR 文件

通过 Application Server Toolkit 在 WebSphere Application Server V6.1 中运行应用程序

运行该应用程序仅涉及到安装 EAR 文件和调用测试 Servlet。您可以在任何受支持的 WebSphere Application Server 部署模型中完成这个任务。在我们的示例中,我们只是直接从 Application Server Toolkit 中执行测试。

  1. 若要从 Application Server Toolkit 中安装应用程序,您所需做的就是将应用程序添加到服务器:

    1. 在 Servers 视图中,右键单击 WebSphere v6.1 Server,并选择 Add and Remove Projects...(参见图 54)。

      图 54. 将项目添加到服务器
      图 54. 将项目添加到服务器
    2. 从 Available 项目选择 OpenJPATestEAR 应用程序,并选择 Add 以将它移动到 Configured projects(参见图 55)。单击 Finish

      图 55. 将可用项目移动到已配置的项目
      图 55. 将可用项目移动到已配置的项目
    3. 同时监视用于启动服务器和应用程序的控制台(参见图 56)。(若服务器未启动,请右键单击并选择 Start。)

      图 56. 应用程序和服务器的控制台消息
      图 56. 应用程序和服务器的控制台消息
  2. 应用程序启动后,您就可以测试该 Servlet:

    1. 展开 OpenJPATestWeb => Servlets => JPATester。右键单击 JPATester,然后选择 Run As => Run on Server(参见图 57)。

      图 57. 测试 servlet
      图 57. 测试 servlet
    2. 选中 Set server as project default (参见图 58)。(只有在首次运行某个项目时才需要这样做。)

      图 58. 设置默认项目
      图 58. 设置默认项目
    3. 浏览器应该打开并显示如图 59 所示的结果。正确运行的 Servlet 将会显示一个无订单的客户,为该客户打开订单,添加一些产品,然后提交该订单。

      图 59. 测试结果
      图 59. 测试结果

结束语

EJB 3 是对 EJB 规范的重大更新,此更新极大地简化了 EJB 编程。Java Persistence API (JPA) 代表了对 EJB 3 规范持久性编程的重大增强。OpenJPA 为开始在 WebSphere Application Server 平台上使用 JPA 提供了重要的机会。通过配置和运行该示例应用程序,您看到了现在使用 JPA 来进行新的开发项目是多么简单。


致谢

作者谨对 Randy Schnier、Jim Knutson、Jonathan Marshall 和 Robert Peterson 为本文所做的贡献表示衷心的感谢。


下载

描述名字大小
样例应用程序OpenJPASample.kws.zip26 KB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere, Open source, Java technology
ArticleID=197653
ArticleTitle=通过 WebSphere Application Server V6.1 利用 OpenJPA
publish-date=11282011