程序员们常常必须决定:如何将表中现有的数据映射到支持 Web 应用程序所需的新的服务器端 Java? 对象。尽管许多开发工具可以帮助程序员构建映射到单个表的单个实体 EJB,但很难找到有以下能力的工具:能帮助程序员创建实体 EJB,且该实体 EJB 映射到非关系数据或由多个数据源管理的数据(可能既有关系数据,也有非关系数据)。本文描述了 DB2 联合 DBMS 如何提供一个分布式数据的虚拟数据库来简化这一任务。
实体 Enterprise JavaBeans™(EJB)开发人员发现自己面临数据建模问题的挑战,这并不稀奇。因为实体 EJB 通常代表由关系 DBMS 管理的数据,所以程序员们常常必须决定:如何将表中现有的数据映射到支持 Web 应用程序所需的新的服务器端 Java™ 对象。尽管许多开发工具可以帮助程序员构建映射到单个表的单个实体 EJB,但很难找到有以下能力的工具:能帮助程序员创建实体 EJB,且该实体 EJB 映射到非关系数据或由多个数据源(可能既有关系数据源,也有非关系数据源)管理的数据。
在本文中,我们将研究 IBM® DB2® 联合数据库管理系统(DBMS)是如何帮助 EJB 程序员解决这些问题的。该技术为程序员提供了全异数据的单站点映象,呈现了一个虚拟数据库,这个虚拟数据库掩盖了远程数据源所需的应用程序编程接口(API)中的差别。这是联合 DBMS 的特征之一,它使 EJB 程序员能以透明和高效的方式使用全异数据。
前一篇文章 处理 Web 应用程序中的全异数据介绍了联合 DBMS 概念并对它们如何能补充 Web 应用程序服务器环境做了说明。另一篇文章 构建访问联合数据的 Web 组件研究了构建使用联合数据的会话 EJB 和 Web 服务的设计需求。在本文中,我们将研究联合 DBMS 技术更进一步的用法:作为创建带有容器管理的持久性(container-managed persistence (CMP))的实体 bean 的基础。但在我们深入研究技术细节之前,理解联合数据库技术在什么情况下可能有益于实体 EJB 程序员是很重要的。
|
CMP 实体 bean 代表着 DB2 联合数据库技术的一种相当完善的用法,因为数据库访问的代码 — 也就是实现持久性的代码 — 是在部署 EJB 时自动生成的。相反,构建访问持久数据的会话 EJB 的程序员,要编写自己的 JDBC 语句才能建立数据库连接以及发出 SQL 语句。
在随后的几节中,我们将讨论如何构建使用联合 DBMS 技术的各种 CMP 实体 bean。IBM 的 WebSphere® Studio Application Developer 集成版(WSADIE)将作为我们的 Java 开发平台。但是,首先要理解在什么情况下使用 DB2 联合技术会对实体 bean 程序员有好处,这很重要。联合技术可以:
|
EJB 是遵守某些编程规范的服务器端软件组件。实体 EJB 代表了通常存储在关系 DBMS 中的持久数据。开发人员可以自己管理他们 bean 的持久方面(通过 bean 管理的持久性,或简称 BMP),但大多数人选择将这一职责委托给容器(通过 容器管理的持久性,或简称 CMP)。本文着重讨论 CMP 实体 bean。
EJB 规范对开发人员制定了某些编码需求。这些需求会稍有不同,取决于您希望支持的 EJB 规范级别。对于本文,我们将着重关注 EJB 1.1,它是 WebSphere Application Server 版本 4(我们的目标部署平台)支持的级别。在部署时,每个 CMP 实体 bean 都有几个代码模块,包括:
开发了 EJB 后,程序员必须设置管理 bean 的特征(如其事务隔离级别)的 部署描述符。最后,必须将这个 bean 打包并部署在 EJB 服务器中。部署过程会导致产生附加的类,其中包括那些与前面描述的 home和 remote接口相关联的类。一个合适的 Java 开发环境(如 WSADIE)在开发、部署和测试 EJB 时会有很大的帮助。
|
在构建访问联合数据的 Java 组件之前,必须配置 DBMS 客户机和服务器环境。 前一篇文章描述了如何配置 DB2 V7.2 客户机以连接 DB2 版本 8 联合 DBMS,后者本身已被设置成可访问远程 Oracle、Sybase 和 Microsoft® SQL Server DBMS 上的数据。我们将不在这里重复所有的详细信息;而仅仅对总体任务进行概括以便您能回想起来。要了解更多信息,请参阅前一篇文章或查询 DB2 产品手册。
要开始进行设置,必须启用 DB2 客户机和服务器平台之间的基本连接(除非客户机和服务器软件安装在同一台机器上)。我们使用 TCP/IP 进行通信,并向每个系统上的 services 文件添加一些项来指定我们使用的服务名和端口号。
启用连接后,我们设置了联合 DBMS 服务器。其步骤包括:
为了确保一切都如预期正常工作,需要在本地对服务器配置进行测试,测试之后,我们配置了客户机平台。其步骤包括:
为了简化 Java 组件的开发和测试工作,我们在客户机上也安装了一个 Java 集成开发环境 — IBM 的 WSADIE 4.1。随 WSADIE 一起安装的还有 WAS 4.0.2 的一个嵌入式副本,它使部署和测试实体 EJB 变得简单。设置 WSADIE 以使用联合数据库的步骤包括:
|
在本文接下来的几节中,我们将循序渐进地指导创建各种 CMP 实体 bean,它们通过 WSADIE 来使用联合数据。这几节适合已熟悉 WSADIE 基本知识的程序员阅读。如果您不知道如何执行某一给定的步骤 — 例如如何创建 EJB 项目或如何在 WebSphere 测试环境中部署 EJB — 请参考产品的联机文档或访问 WebSphere 开发者园地 http://www.ibm.com/webspere/developer,并遵循他们的一些产品教程。
|
正如我们在以前的文章中提到的, 别名代表了 DB2 的远程数据。对于已用 DB2 联合技术创建的别名,EJB 程序员可以使用 WSADIE 创建 CMP 实体 bean 来映射到这些别名。在我们的测试环境中,我们创建了各个实体 bean,分别映射到与各个 Oracle、Sybase 和 Microsoft SQL Server 表关联的别名。当然,DB2 联合技术支持对其它数据源的访问(包括非关系数据源);对于来自其它数据源的数据,创建映射到代表该数据别名的 CMP 实体 bean,过程是相同的。然而,如果 DB2 对某一给定的数据源施加了任何数据访问限制,那么您可能需要做些额外的工作。例如,DB2 支持对某些数据源的只读访问。如果对涉及这些数据源的别名构建 CMP 实体 bean,那么应该修改 bean 代码以避免写尝试。在后面的一节中,当我们讨论如何构建映射到一个视图(该视图连接或合并来自多个数据源的数据)的 CMP 实体 bean 时,我们将知道如何做到这一点。这样的视图本质上是只读的。
在 WSADIE 4.1 中,自顶向下建模是支持使用联合数据开发 CMP 实体 bean 的唯一方法。尽管用自顶向下建模工具来使用现有数据可能显得违反直觉,但它实际上是一个能取得预期结果的简单方法:为别名生成一个有效的 CMP 实体 bean。
开发这样的 CMP 实体 bean 要遵循以下步骤:
|
对于您希望表示成 CMP 实体 bean 的数据,如果它的别名不存在,仍可以使用 WSADIE 来构建和部署您的 bean。其过程与 前一节描述的过程几乎相同。您仍将使用 WSADIE 的 EJB 开发向导的自顶向下建模支持来对您的 bean 建模。然而,在实际试图使用 bean 以前,您需要为远程数据创建一个 DB2 别名。如果还没有为远程数据源创建必需的数据对象或表,那么还需要预先创建它。可以遵循 DB2 手册中的指示,手工执行这些任务。或者使用由 WSADIE 生成的 DDL 使该过程部分自动化。这里,我们将描述后一种选择。
DB2 的联合技术以关系 DBMS 的 SQL 数据定义语言(DDL)透明性为特色。这意味着可以使用 DB2 的 CREATE TABLE .... OPTIONS 语法用一条语句执行两个独立的任务:在期望的远程数据源处创建一个表,并创建该表对应的 DB2 别名。使用 DDL 透明特性可简化您的工作,因为 DB2 会执行任何必需的 SQL 转换来正确地构造远程表;您不需要学习该数据源特定的 SQL 语法来创建有效的表。我们将使用这一 DDL 透明特性在远程数据源处创建一个新的表,并为该表创建新的别名,该别名最终将由 CMP 实体 bean 使用。
开发这样的 CMP 实体 bean 要遵循以下步骤:
CREATE TABLE MYTABLE (COL1 INT,
COL2 INT) |
CREATE TABLE SCHEMANAME.MYTABLE (COL1 INT PRIMARY KEY NOT NULL, COL2 INT) |
CREATE TABLE SCHEMANAME.MYTABLE
(COL1 INT PRIMARY KEY NOT NULL,
COL2 INT)
OPTIONS (REMOTE_SERVER 'ORACLE8',
REMOTE_SCHEMA 'ORACLEUSER1') |
下面是来自作者的测试环境的一个完整示例:
-- Generated by Relational Schema Center of WSADIE
CREATE SCHEMA user1;
CREATE TABLE user1.FOOBAR
(ID INTEGER NOT NULL,
NAME VARCHAR(250));
ALTER TABLE user1.FOOBAR
ADD CONSTRAINT FOOBARPK PRIMARY KEY (ID);
-- Revised DDL
CREATE TABLE user1.FOOBAR
(ID INTEGER PRIMARY KEY NOT NULL ,
NAME VARCHAR(250))
OPTIONS (REMOTE_SERVER 'ORACLE8',
REMOTE_SCHEMA 'ORACLEUSER1') |
可以在 DB2 命令窗口(Command Window)中、在 DB2 命令行(Command Line)上、或通过 DB2 命令中心(Command Center)(可通过 DB2 控制中心(Control Center)进入)执行修改后的 DDL 语句。
|
联合 DBMS 技术一个特别有趣的方面在于它能表示来自多个远程数据源的数据,就好象该数据是单一的本地管理的对象的一部分。管理员可以创建这样的视图:视图可以连接或合并来自多个表(或其它数据表现形式)的数据,而这些表驻留在由不同供应商制造的多个数据服务器上。对于 EJB 程序员来说,这提供了新的数据建模机会。可以较容易地构建单个 CMP 实体来跨越多个数据源。由于关系 DBMS 常见的视图更新约束,这样的 bean 本质上是只读的,尽管如此,它们仍然提供了通过标准 EJB 技术集成全异数据的方法。在本节中,我们将讨论程序员如何用 WSADIE 通过三个步骤来构建这样的 bean:
同任何关系 DBMS 一样,DB2 使管理员能够创建跨越多个表的数据视图。DB2 的联合数据库技术扩展了视图的能力,因而它们可以包含来自多个服务器以不同本机格式存储的数据。要构建这样的视图,首先要为远程数据对象创建期望的别名。然后使用 SQL 创建一个连接或合并这些别名的视图。
在我们的环境中,我们利用 DB2 的 DDL 透明特性在 Oracle 和 SQL Server 数据库中创建表,并在我们的 DB2 联合数据库中创建这些表的别名。
create table orarest ( id int primary key not null, name varchar(20), cuisine varchar(20), budget int) options (remote_server 'ORACLE8', remote_schema 'ORACLEUSER1') create table msrest ( id int primary key not null, name varchar(20), cuisine varchar(20), budget int) options (remote_server 'MSSQL', remote_schema 'MSUSER1') |
这使得下面的对象将被创建:
create view multirest (id, name, cuisine, budget) as select id, name, cuisine, budget from orarest union select id, name, cuisine, budget from msrest |
然后,我们使用该视图作为 CMP 实体 bean 的基础(在下一节描述)。
创建视图后,您可以用 WSADIE 创建一个 CMP 实体 bean 来表示这一数据。其过程与 为现有的别名创建 CMP 实体 bean 中概括的方法非常相似。然而,如前所述,这样的视图本质上是只读的。如果您接受所有的缺省设置而不采取进一步的行动,那么在 EJB 容器试图执行与创建、除去和查找 EJB 相关联的方法时,会出现运行时异常。所有这样的方法都准备或试图执行数据库写操作,这对于我们正在使用的视图类型是无效的。(缺省情况下,生成的 findByPrimaryKey() 方法执行 SELECT ... FOR UPDATE ,这意味着将来可能会出现一个写操作。对于这里的视图定义来说,这种操作是无效的)。
此外,试图设置属性值的 EJB 业务方法(“setter”方法)将导致运行时异常的出现,因为它们也会启动数据库写操作。在本节和下一节中,我们将看到如何通过 EJB 编程向导来修改缺省值,以及如何定制生成的 EJB 部署代码以防止出现不必要的数据库写操作尝试,同时也使抛出的异常更容易说明:为什么给定的底层数据模型不支持某些 EJB 操作。
要创建这样的 CMP 实体 bean:
在为部署您的 bean 而生成的代码中,有一小部分必须修改,以防止 create() 和 remove() 方法试图从 bean 所基于的视图插入和删除数据。从 bean 的 home 接口除去 create() 和 remove() 方法是不能接受的,因为 EJB 规范要求这些方法必须存在。将这些方法的访问意图设置为只读也是没有意义的,因为它们旨在产生 INSERT 和 DELETE 语句。相反,您应该修改这些方法的逻辑,以便抛出合理的异常而不是试图去写数据库。本节描述了应修改哪些生成的方法,并说明了如何这样做。但是,请注意,每当您为 bean 生成了新的部署代码,都需要修改这些方法。没有办法指示 WSADIE(或 WebSphere Application Server)在重新生成代码时保留您的更改。
要修改生成的代码,请遵循以下步骤:
public void remove (Object arg0) throws .... {
throw new RemoveException("This EJB is mapped
to a view and cannot be removed.");
// comment out generated code below
...
}
public void remove (Handle arg0) throws .... {
throw new RemoveException("This EJB is mapped
to a view and cannot be removed.");
// comment out generated code below
...
}
|
public MultiRest create(...) throws ... {
throw new CreateException("This EJB is mapped
to a view. New instances cannot be created.");
// comment out generated code below
...
}
|
public void remove() throws .... {
throw new RemoveException("This EJB is mapped
to a view and cannot be removed.");
// comment out generated code below
...
}
|
|
本文与前两篇文章一起,共同描述了如何将联合 DBMS 和 Web 应用程序服务器技术结合起来,为 Java 开发人员集成来自多个数据源的数据提供了新的选择。可能的好处包括以下能力:
在对于应用程序很关键的数据存在于多个数据源中,以及可使用数据库管理技能来解决管理问题时,是考虑这样的技术结合的最佳时机。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/374079/viewspace-130343/ ,如需转载,请注明出处,否则将追究法律责任。