使用 Apache OpenJPA 开发 EJB 3.0 应用,第 2 部分: 开发第一个 Open JPA 应用

在 上一部分中,我们了解了 EJB 3.0 标准和 OpenJPA 的基本特性,现在我们将开始讲述如何使用 OpenJPA 开发企业应用。本文中,我们将假设有一个 Animal 对象,在某一个应用场景中,我们需要使用 OpenJPA 框架提供的工具和接口完成 Animal 对象的持久化、属性修改、删除、查找功能。本文将通过简单的文字和代码描述使用 OpenJPA 开发的步骤和方法,以及开发过程中如何使用 OpenJPA 提供的工具协助完成开发任务。

下载及安装 OpenJPA

支持环境准备

由于 OpenJPA 是基于注释机制的框架,这需要用到 JDK 5.0 或者以上版本,因此请确保在工作机器上已经下载和安装了 JDK 5.0(参见 参考资源)。

演示过程中,我们需要一个数据库作为对象持久化的目标数据库。出于简单和方便的考虑,我们选择采用 MySQL 数据库,因此您需要下载 MySQL 数据库安装包(请见 参考资源)。如果需要 MySQL 很好的支持中文字符(GB2312 编码),您可选择下载 MySQL 5.0 或者以上版本,安装的时候选择数据库字符集为 GB2312 即可。

下载、安装 OpenJPA

OpenJPA 的最新稳定版本是 Open JPA 0.97(下载链接见 参考资源)。OpenJPA 的安装比较简单,只需要将下载的压缩文件解压即可。我们假设将下载的压缩包解压到 C:/OpenJPA 目录下(本文后面将使用 %OPENJPA_HOME% 来引用这个目录)。

使用 OpenJPA 开发 EJB 3.0 应用

成功安装 OpenJPA 后,我们就可以开始应用 OpenJPA 框架开发 EJB 3.0 应用了。下面的章节中我们将讲述应用 OpenJPA 框架开发 EJB 3.0 应用的主要步骤。为了把描述集中在 OpenJPA 本身而不涉及太多的其它内容,在本演示场景中,我们在轻量级应用中来使用 OpenJPA,开发出的应用基于 Java SE 环境运行,而不依赖于 EJB 容器,关于如何在 Java EE 中配置使用 OpenJPA 将是另外一个主题,本文将暂不涉及,本系列的后续文章中将会讨论这个主题。

通常情况下,使用 OpenJPA 框架开发持久层主要有以下步骤:

  1. 编写(或修改)OpenJPA 配置文件;

    在非 JavaEE 环境下,OpenJPA 通常使用 CLASSPATH 环境下的 META-INF\persistence.xml 文件来创建 EntityManagerFactory,而每一个被管理的 Java 实体类必须在 persistence.xml 中注册后才能被 EneityManager 处理。

  2. 根据业务需要设计 Java 对象、编写对应的 Java 实体类;
  3. 用 JDK 编译 Java 实体类;
  4. 用 OpenJPA 提供的工具 — PCEnhancer 来增强(enhance)编译好的 Java 实体类;被增强过的类可以提供更好的运行性能、灵活的 "懒加载" 等方面的优势,更多详细的内容请参考 OpenJPA 的帮助文档。
  5. 使用 OpenJPA 提供的工具 MappingTool 从 Java 对象生成数据库定义文件(DDL);

    可以通过 MappingTool 工具直接保持 Entity 和数据库之间的一致性,也可以使用 MappingTool 工具生成的数据库定义文件(DDL)创建应用正常运行所需要的数据库结构。

  6. 将创建的实体类注册到 OpenJPA 容器中;
  7. 应用 JPA 接口编写实体类访问代码,实现相应的业务逻辑。

下面我们将用一个简单的例子来说明创建 OpenJPA 应用的典型步骤,实例中我们将创建名为 Animal 的持久化对象,它有两个属性,分别是 “id”和 “name”,Animal 对象将被持久化到本地的 MySQL 数据库中,其中 id 属性对应的数据库字段由 MySQL 数据库自动生成。

 

开发环境说明

本文的演示说明均基于 Windows XP 平台,JDK 版本为 1.5.0_11,数据库服务器为 MySQL 5.0,和演示代码位于同一台机器上。所有演示用例对应的 MySQL 数据库为“openjpa”,访问 MySQL 的用户名和密码也均为“openjpa”。


OpenJPA 应用开发典型步骤

请读者注意,后面章节中关于操作的说明均基于 Windows XP 操作系统,如果您使用的开发环境运行在其它类型的操作系统之上,请根据实际情况做出相应的调整。


建立工程目录

在 C: 盘根目下创建名为 OpenJPAExamples 的目录,我们所有的类文件和配置文件都将放在这个目录下。


编写 JPA 配置文件

在 C:\OpenJPAExamples 新建 META-INF 目录,随后在该目录下创建 persistence.xml 文件。persistence.xml 是 OpenJPA 的配置文件,提供 OpenJPA 容器初始化、运行所需要的配置信息。比如 OpenJPA 的事务策略、数据库的连接信息等。清单 1 中是我们演示实例中所使用的 persistence.xml 文件的内容。

清单 1 META-INF\persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
<!-- persistence-unit 的 name 属性提供了创建 EntityManagerFacotry 时的关键字,transaction-type 则指定了使用的事务管理类型,这里使用‘ RESOURCE_LOCAL ’参数表示使用本地事务 -->
<persistence-unit name="mysql" transaction-type="RESOURCE_LOCAL">
<!-- JPA 的提供类,OpenJPA 的设置如下,如果使用其它的 JPA 实现,这里的内容需要修改成相应的提供类 -->
<provider>
org.apache.openjpa.persistence.PersistenceProviderImpl
</provider>
<!-- OpenJPA 容器中管理的实体类列表 -->
<class>org.vivianj.openjpa.entity.Animal</class>
<!-- OpenJPA 容器访问数据库的参数-->
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost/openjpa" />
<property name="openjpa.ConnectionDriverName" value="com.mysql.jdbc.Driver" />
<property name="openjpa.ConnectionUserName" value="openjpa" />
<property name="openjpa.ConnectionPassword" value="openjpa" />
</properties>
</persistence-unit>
</persistence>

创建实体类

新创建实体类 Animal,为了说明的简单,该类只有两个属性:id 和 name,其中 id 字段代表的是编号(编号由 MySQL 数据库自动生成),name 属性表示名称。实体类的全部代码见清单 2,请注意其中的黑体部分,它们是 JPA 中定义的注释(Annotation),Animal 中仅仅用到了非常少的几个注释,了解其它更多注释的细节请参看 OpenJPA 的帮助文档。


清单 2 Animal.java

package org.vivianj.openjpa.entity;

import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/*
* 使用 Entity 注释表示该类是实体类,它的 name 属性是该实体在查询中对应的
* 唯一名称,如果没有提供 Entity 的 name 属性,默认的 name 属性是类名。
*/
@Entity
public class Animal {
// 编号
/* 使用 Id 注释表示该字段是标识字段 */
@Id
/*
* 使用 GeneratedValue 注释定义该标识字段的产生方式,我们的演示系统中 id 由 MySQL 数据库字段自动生成,因此选择
* GenerationType.IDENTITY, 另外的可选方式包括
* GeneratorType.AUTO,GenerationType.SEQUENCE, GenerationType.TABLE。
*/
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

// 名称
/*
* Basic 注释表示该属性是持久化属性,没有使用 Basic 注释的属性将不会 被持久化到数据库中
*/
@Basic
private String name;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}


编译实体类

打开命令行控制台,进入 C:\OpenJPAExamples 目录,执行下面的系列语句可以编译实体类 Animal.java。

C:\OpenJPAExamples>set OPENJPA_HOME=C:\OpenJPA 
C:\OpenJPAExamples>set classpath=%OPENJPA_HOME%\lib\persistence-api-1.0.jar
C:\OpenJPAExamples>javac Animal.java -d

[ 注 ] 上面的命令行中第一行出现的 C:\OpenJPA 是指 OpenJPA 框架的安装目录。如果您没有使用 C:/OpenJPA 作为 OpenJPA 的安装目录,请将 OPENNJPA_HOME 的值修改为您安装 OpenJPA 的目录。

增强(Enhance)实体类

Enhance 是使用 OpenJPA 必须的一个步骤,所谓 Enhance 是指使用 OpenJPA 提供的工具 PCEnhancer(org.apache.openjpa.enhance.PCEnhancer)对实体类进行处理的过程,被 Enhance 过的实体类能够支持性能优化、懒惰式装载等高级特性。

OpenJPA 支持在编译时、部署时、运行时增强实体类,我们以编译时为例了解如何增强实体类。我们使用下面的系列语句完成实体类的增强(Enhance)。

C:\OpenJPAExamples>set OPENJPA_HOME=C:\OpenJPA 
C:\OpenJPAExamples>set classpath= %OPENJPA_HOME%\lib\commons-collections-3.2.jar;
%OPENJPA_HOME%\lib\commons-lang-2.1.jar;
%OPENJPA_HOME%\lib\commons-logging-1.0.4.jar;
%OPENJPA_HOME%\lib\commons-pool-1.3.jar;
%OPENJPA_HOME%\lib\geronimo-j2ee-connector_1.5_spec-1.0.1.jar;
%OPENJPA_HOME%\lib\geronimo-jms_1.1_spec-1.0.1.jar;
%OPENJPA_HOME%\lib\geronimo-jta_1.0.1B_spec-1.0.1.jar;
%OPENJPA_HOME%\lib\persistence-api-1.0.jar;
%OPENJPA_HOME%\lib\serp-1.11.0.jar;
%OPENJPA_HOME%\openjpa-all-0.9.6-incubating.jar
C:\OpenJPAExamples>java org.apache.openjpa.enhance.PCEnhancer Animal.java

有兴趣的读者可以使用反射(Reflect)机制获取经过 Enhance 的类的信息,清单 3 中给出了被 Enhance 过后 Animal 实体类的类声明和方法签名信息,从中我们可以看到 Animal 被增加了新的 org.apache.openjpa.enhance.PersistenceCapable 接口,而该接口声明的方法都是和实体创建、状态保持等相关的。事实上,OpenJPA 通过 Enhance 过程修改我们的实体类,扩充了实体类的能力,从而实现性能优化、懒惰式装载等高级特性。

package org.vivianj.openjpa.entity;

import org.apache.openjpa.enhance.FieldConsumer;
import org.apache.openjpa.enhance.FieldSupplier;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.enhance.StateManager;

public class Animal implements org.apache.openjpa.enhance.PersistenceCapable {

protected transient org.apache.openjpa.enhance.StateManager pcStateManager;
protected transient byte pcFlags;
static java.lang.Class class$Ljava$lang$String;
static java.lang.Class class$Lorg$vivianj$openjpa$entity$Animal;
public org.vivianj.openjpa.entity.Animal();
public int getId();
public void setId(int);
public java.lang.String getName();
public void setName(java.lang.String);
static final {};
static java.lang.Class class$(java.lang.String);
protected void pcClearFields();
public org.apache.openjpa.enhance.PersistenceCapable pcNewInstance(org.apache.openjpa.enhance.StateManager, java.lang.Object, boolean);
public org.apache.openjpa.enhance.PersistenceCapable pcNewInstance(org.apache.openjpa.enhance.StateManager, boolean);
protected static int pcGetManagedFieldCount();
public void pcReplaceField(int);
public void pcReplaceFields(int[]);
public void pcProvideField(int);
public void pcProvideFields(int[]);
protected void pcCopyField(org.vivianj.openjpa.entity.Animal, int);
public void pcCopyFields(java.lang.Object, int[]);
public java.lang.Object pcGetGenericContext();
public java.lang.Object pcFetchObjectId();
public boolean pcIsDeleted();
public boolean pcIsDirty();
public boolean pcIsNew();
public boolean pcIsPersistent();
public boolean pcIsTransactional();
public boolean pcSerializing();
public void pcDirty(java.lang.String);
public org.apache.openjpa.enhance.StateManager pcGetStateManager();
public java.lang.Object pcGetVersion();
public void pcReplaceFlags();
public synchronized void pcReplaceStateManager(org.apache.openjpa.enhance.StateManager) throws java.lang.SecurityException;
public void pcCopyKeyFieldsToObjectId(org.apache.openjpa.enhance.FieldSupplier, java.lang.Object);
public void pcCopyKeyFieldsToObjectId(java.lang.Object);
public void pcCopyKeyFieldsFromObjectId(org.apache.openjpa.enhance.FieldConsumer, java.lang.Object);
public void pcCopyKeyFieldsFromObjectId(java.lang.Object);
public java.lang.Object pcNewObjectIdInstance(java.lang.Object);
public java.lang.Object pcNewObjectIdInstance();
public java.lang.Boolean pcIsDetached();
public java.lang.Object pcGetDetachedState();
public void pcSetDetachedState(java.lang.Object);

}

将新创建的实体类注册到 OpenJPA 容器中

在 OpenJPA 框架中,如果创建了新的实体类,必须通过修改配置文件,将它注册到 OpenJPA 容器中,该实体类才能够被 OpenJPA 管理。将实体类方法注册到 OpenJPA 容器中的方法是在 persistence.xml 中对应的 persistence-unit 元素下增加子元素 class,元素的内容就是被注册持久类的全名。比如我们要把 org.vivianj.openjpa.entity.Animal 注册到 OpenJPA 容器中,我们可以在 persistence.xml 中加入如下内容:

   <persistence > 
<persistence-unit >

<class>org.vivianj.openjpa.entity.Animal</class>

</persistence-unit>
</persistence>

准备数据库

在 MySQL 数据库中新建名为“openjpa”的数据库。新创建数据库的访问用户为“openjpa”,密码设置为“openjpa”,新创建的用户“openjpa”必须具有访问读写“openjpa”数据库数据的权限。

保持实体类和数据库表结构一致性

OpenJPA 中提供了专门的 MappingTool(org.apache.openjpa.jdbc.meta.MappingTool)工具协助开发者保持实体类和数据库表结构之间的一致性。MappingTool 工具能够自动的根据实体类中提供的注释(Annotation),识别出对象、对象之间的继承 / 包含等关系以及如何在关系型数据库中处理这些关系的设置,自动保证实体类和数据库之间的一致性,开发者也可以选择使用 OpenJPA 生成创建数据库所需要的 SQL 语句,然后手动的保持实体类和数据库之间的一致性。

可以使用下面的命令语句直接通过 MappingTool 在数据库中创建 OpenJPA 应用所需要的数据库表。

java org.apache.openjpa.jdbc.meta.MappingTool Animal.java

命令执行完成后,我们通过 MySQL 的客户端访问 OpenJPA 数据库,可以发现里面已经创建了名为“animal”的数据表。如果开发者不想让 MappingTool 自动维护 OpenJPA 和数据库之间的映射,而只是想让 MappingTool 协助生成创建数据库所需要的数据库表定义文件(DDL),可以使用下面的命令语句,其中的参数 -sql 的值就是生成数据库表定义文件的位置。

比如要将生成的数据库表定义文件写入当前文件夹下 animal.sql 文件的命令如下:

java org.apache.openjpa.jdbc.meta.MappingTool – sql animal.sql Animal.java

[ 注 ] 要成功执行 MapptingTool 工具,必须先将数据库的 JDBC 驱动放入到 classpath 中,否则会得到一个 org.apache.openjpa.util.StoreException 类型的异常信息。

访问持久化对象

访问 OpenJPA 容器中管理的持久化对象所需要的基本步骤如下:

  1. 获取 OpenJPA 容器中配置好的 EntityManagerFactory 对象;
  2. 从 EntityManagerFactory 中获取 EntityManager 对象;
  3. 如果是处理持久化对象的创建、更新、删除动作,还需要从 EntityManager 中获取 EntityTransaction,并且调用其 begin(commit)方法显式的启动(提交)事务;
  4. 操作持久化对象
    1. 调用 EntityManager 的 persist 方法可以持久化对象到数据库中;
    2. 调用 EntityManager 的 merge 方法可以更新对象状态;
    3. 调用 EntityManager 的 remove 方法可以删除持久化对象,另外一种选择是通过 Query 接口删除对象。
  5. 查询持久化对象
    1. 根据对象的主键查找符合条件的对象,可以直接使用 EntityManager 的 find 方法;
    2. 要查询 EntityManager 中符合条件的对象列表,还需要借助 Query 接口和 JPQL(Java Persistence Query Language)查询语言。

下面的章节中我们将逐一了解如何通过 OpenJPA 中的相关接口完成这些步骤。


获取 OpenJPA 容器中的 EntityManagerFactory

EntityManagerFactory 是 OpenJPA 中创建 EntityManager 的工厂,要想得到 EntityManager,就必须获取的相应的 EntityManagerFactory。

EntityManagerFactory 通过 Persistence 的静态方法 createEntityManagerFactory 获得,该方法是一个重载的方法,支持不同的输入参数。最常用的是使用一个字符串作为参数,该字符串的内容是 EntityManagerFactory 的标识名,该标识名需要和 persistence.xml 文件中的 persistence-unit 元素的 name 属性保持一致。可以使用 null 作为 createEntityManagerFactory 方法的参数,这时候将使用 persistence.xml 中没有提供 name 属性的 persistence-unit 元素提供的参数来配置 EntityManagerFactory。

下面的代码段可以从 OpenJPA 容器中获取名为“mysql”的 EntityManagerFactory。

EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysql");

而它对应的 persistence.xml 文件中,应该有相应的 name 属性为“mysql”的 persistence-unit 元素,下面的配置是一个示例。

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
<persistence-unit name="mysql" transaction-type="RESOURCE_LOCAL">
</persistence-unit>
</persistence>

为了提升软件的执行效率,我们通常选择在某一个范围内缓存 EntityManagerFactory 对象。在 EntityManagerFactory 使用完后,我们需要调用它的 close 方法来释放相应的资源。获取、使用 EntityManagerFactory 的实际例子 请参考 清单 4 AnimalDAOImpl.java 中的源代码。

获取 EntityManager

要访问 OpenJPA 容器中的实体类,必须首先获得相应的 EntityManager。可以通过 EntityManagerFactory 对象的 createEntityManager() 方法来获取 EntityManager 对象。获取、使用 EntityManager 的实际例子请参考 清单 4 AnimalDAOImpl.java中的源代码。


EntityTransaction 的启动(提交)

对于 OpenJPA 容器中的持久化对象的创建、修改、删除操作必须在代码中显式的处理事务,而对于查询操作则不需要在代码中显式的处理事务。JPA 应用中的事务由 EntityTransaction 接口处理,EntityTransaction 可以直接通过 EntityManager 对象的 getTransaction 方法获得。我们可以调用 EntityTransaction 的 begin(commit) 方法显式的启动(提交)事务。获取、使用 EntityTransaction 的实际例子请参考 清单 4 AnimalDAOImpl.java中的源代码。


Query 接口和 JPQL 查询语言

要查询 EntityManager 中符合条件的对象列表,需要借助 Query 接口和 JPQL。Query 接口可以直接通过 EntityManager 的 createQuery 方法获得。Query 对象目前支持 JPQL 和原生态 SQL 两种方式。

JPQL 是 OpenJPA 中支持的对象查询语言,是 EJB SQL 的一种实现。通过 JPQL,我们可以用一种面向对象的方式编写持久化对象的查询条件。比如要查找编号为“1”的 Animal 对象,我们可以使用下面的 JPQL 语法:

select animal form Animal animal where animal.id=1)

关于 JPQL 的更多信息请参考 OpenJPA 的帮助文档。Query 接口和 JPQL 的实际例子请参考 清单 4 AnimalDAOImpl.java中的源代码。

清单 4 中列出了如何使用 OpenJPA 操作、查找持久化对象 Animal 的源代码,读者可以从中了解使用 OpenJPA 时所应该完成的步骤和方法。


清单 4 AnimalDAOImpl.java

package org.vivianj.openjpa.impl.ejb3;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

import org.vivianj.openjpa.dao.AnimalDAO;
import org.vivianj.openjpa.entity.Animal;

/**
* AnimalDAOImpl 演示了如何使用 OpenJPA 访问数据库的方法和步骤
*
*/
public class AnimalDAOImpl implements AnimalDAO {

/**
* removeAnimal 方法可以从数据库中删除指定编号的 Animal 对象
*
*
@param id
* Animal 对象的编号
*/
public void removeAnimal(int id) {
// 获取 EntityManagerFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysql");
// 获取 EntityManager
EntityManager em = factory.createEntityManager();
// 开始事务处理
em.getTransaction().begin();
// 使用 Query 删除对象
em.createQuery("delete from Animal animal where animal.id=" + id).executeUpdate();
// 我们还可以选择通过 Query 对象来完成
/*
* // 从 EntityManager 中查询到符合条件的对象 Animal animal =
* em.find(Animal.class,id);//调用 EntityManager 的 remove 方法删除对象
* em.remove(animal);
*/
// 提交事务
em.getTransaction().commit();
// 关闭 EntityManager
em.close();
// 关闭 EntityManagerFactory
factory.close();

}

/**
* findAnimalsByName 通过输入的 name 内容模糊查找符合条件的 Animal 对象列表
*
*
@param name
* Animal 对象的 name
*
@return 符合模糊查找条件的 Animal 对象列表
*/
public List<Animal> findAnimalsByName(String name) {
// 获取 EntityManagerFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysql");
// 获取 EntityManager
EntityManager em = factory.createEntityManager();
/*
* 通过 EntityManager 的 createQuery 方法获取 Query 对象 createQuery 方法的参数是 JPQL
* 查询语句,JPQL 语句的语法请参考 OpenJPA 的 帮助文档. 由于查询不需要事务的支持,因此 Query 操作的前后没有出现
* begin、commit 方法的调用
*/
Query q = em.createQuery("select animal from Animal animal where animal.name like '%" + name + "%' ESCAPE ''");
List<Animal> l = q.getResultList();
// 关闭 EntityManager
em.close();
// 关闭 EntityManagerFactory
factory.close();
return l;
}

/**
* getAnimalByPrimaryKey 方法可以查找符合条件的单个 Animal 对象, 如果不存在对应的 Animal 对象将返回 null
*
*
@param id
* Animal 对象的编号
*
@return 唯一符合条件的 Animal 对象
*
*/
public Animal getAnimalByPrimaryKey(int id) {
// 获取 EntityManagerFactory
EntityManagerFactory factory = Persistence
.createEntityManagerFactory("mysql");
// 获取 EntityManager
EntityManager em = factory.createEntityManager();
// 查找符合条件的对象
Animal animal = em.find(Animal.class, id);
// 关闭 EntityManager
em.close();
// 关闭 EntityManagerFactory
factory.close();
return animal;
}
/**
* 将对象持久化到数据库中
*
*
@param animal
* 需要被持久化的对象
*/
public void persistAnimal(Animal animal) {
// 获取 EntityManagerFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysql");
// 获取 EntityManager
EntityManager em = factory.createEntityManager();
// 开始事务处理
em.getTransaction().begin();
// 持久化对象
em.persist(animal);
// 提交事务
em.getTransaction().commit();
// 关闭 EntityManager
em.close();
// 关闭 EntityManagerFactory
factory.close();
}

/**
* 将 Animal 对象被更新的属性持久化到数据库中
*
*
@param animal
* 被更新过的 Animal 对象
*/
public void updateAnimal(Animal animal) {
// 获取 EntityManagerFactory
EntityManagerFactory factory = Persistence.createEntityManagerFactory("mysql");
// 获取 EntityManager
EntityManager em = factory.createEntityManager();
// 开始事务处理
em.getTransaction().begin();
// 更新持久化对象状态
em.merge(animal);
// 提交事务
em.getTransaction().commit();
// 关闭 EntityManager
em.close();
// 关闭 EntityManagerFactory
factory.close();

}

}

总结

本文中首先描述了如何准备 OpenJPA 开发环境所需要的支持环境,接着说明了 OpenJPA 下载、安装的步骤。随后,通过一个简单的例子,作者讲解了如何应用 OpenJPA 开发 EJB 3.0 应用的步骤和方法,并且通过合适的代码演示了如何使用 JPA 标准接口访问持久化对象。

在本系列的 下一部分中,我们将介绍 OpenJPA 对实体继承的三种支持方式,我们还将通过简单的例子来介绍其中的一种方式的具体实现细节。

第 1 部分: OpenJPA 与 EJB 3.0

第 3 部分: 实体继承

posted @ 2012-01-23 20:32  saintaxl  阅读(820)  评论(0编辑  收藏  举报