快捷搜索:

将 DBMS 存储过程封装为会话 EJB 组件中的方法

将 DBMS 存储历程封装为会话 EJB 组件中的措施 作者:Cynthia M. Saracco

集成 Web 利用办事器和数据库治理 (DBMS) 技巧是很多新型商业利用的常见需求。在本文中,我们将评论争论该集成的一个方面:若何在会话 Enterprise JavaBeans (EJB) 组件中设计与开拓封装或调用现有 DBMS 存储历程的措施。您应该认识 EJB 技巧、布局化查询说话 (SQL) 和 Java 数据库连接 (JDBC) 的基础常识,以便充分理解本文。

假如您正致力于必要造访或改动在 DMBS 中数据的 Web 利用法度榜样开拓,那么可能已经在向基于 EJB 的设计转移。您可能会发明,经由过程使会话 EJB 组件使用 DBMS 存储历程,可以削减编码和掩护事情,并可能前进数据造访机能。

一些公司多年来不停在应用存储历程(stored procedure),很大年夜程度上是由于它们可以赞助削减收集通信量,并前进散播式谋略情况中的机能。平日,这些历程包孕涉及多半据库操作的紧张营业逻辑。远程利用法度榜样调用这些历程,在 DMBS 办事器上履行它们所包孕的 SQL 语句。当然,历程停止时,所有结果都返回给利用法度榜样。

这些旧有存储历程对 Web 利用平日是有用的。与其在 EJB 组件中复制这些逻辑,为什么不将这些历程作为措施封装在会话 bean 中呢?这样可以避免 DBMS 办事器和 EJB 组件中的冗余代码 -- 在斟酌开拓、调试和掩护开销时,冗余代码将损耗开拓效率。这还可能带来前进机能的好处。调用存储历程可以削减 EJB 组件蓝本不得不发出的 SQL 语句数量,从而削减与远程 DBMS 的通信开销。

入门

现在明白为什么要从会话 bean 调用存储历程了吧,下面我们看看若何开始。首先,必要应用适当的开拓情况,该情况应该包括一个带有内置 EJB 支持的 Java 开拓对象,一个 Web 利用办事器和一个关系 DBMS。我的参考设置设置设备摆设摆设包括 VisualAge for Java 企业版 3.0.2,WebSphere Application Server 高档版 3.0.2.1,以及 DB2 V7.1,所有这些都安装在一个 Windows NT 系统上。有关若何设置设置设备摆设摆设该情况以支持本文所述事情的具体信息,请参阅 "Leveraging DBMS Stored Procedures through Enterprise JavaBeans"(位于参考资猜中)或参考产品手册。

有了精确的软件情况,就可以开始了。虽然我们要评论争论的编码模式可能得当于无状态会话(stateless session) bean,但它也可应用有状态会话(stateful session) bean 组件。然则,由于无状态会话 bean 比有状态会话 bean 耗损的系统资本更少,而且涉及的代码也更少,以是平日建议应用无状态会话 bean。

首先要斟酌的设计问题是若何在存储历程和 EJB 组件之间映射数据。存储历程可能必要多个输入、输出和输入/输出参数,并返回一个或多个结果集(代表数据行)。除非要对不合类型的历程应用不合的编码模式,您必要编写 EJB 组件以便处置惩罚所有这些可能性。

处置惩罚输入(或者输入/输出)参数很简单:将存储历程必要的每个参数映射成 EJB 组件的输入参数。然则,处置惩罚存储历程的输出对照棘手。可能有多个输出参数和多个结果集要传回调用法度榜样,必要将这些作为一个可序列化的工具返回,以相符 EJB 规范。可以编写自己的类,使其可以将这些数据打包成一个工具,并在该工具中包括所有必须的元数据。(该元数据将描述工具的内部布局,以便客户机知道若何处置惩罚。)但这必要大年夜量事情。

假如正在应用 VisualAge for Java 和 WebSphere,那么,有个更好的选项:应用它们的数据造访 Bean (DAB) 库。该库包孕一些供给位于基础 JDBC 之上的函数层的类。可能会发明 com.ibm.db.CallableStatement 类分外方便,由于它容许创建一个可序列化的工具,该工具包孕所有从存储历程返回的输出,包括多个结果集(假如有的话)和相关元数据。还有一个好处是,该库设计成可以支持任何支持 JDBC 的数据源,是以,它可以使 bean“与 DBMS 无关”。有了 DAB 库,就可以用一个编码模式在会话 EJB 组件中封装任何存储历程。以致可以在 EJB 客户机中应用一个通用的编码模式,来处置惩罚任何从封装器措施返回的结果。

回首开拓义务

我们来评论争论一下应用通用编码模式,来集成 EJB 组件和 DBMS 存储历程的步骤:

确定要将哪个存储历程封装成 EJB 措施。假如该历程不存在,则遵照 DBMS 标准历程来创建和调试。

确定要应用哪个无状态会话 EJB 组件。假如该 EJB 不存在,则遵照 Java 开拓情况的标准历程来创建和调试。

扩展 EJB 组件的远程接口,以包括用于封装存储历程的新措施。

扩展 EJB 组件的实现,以包括封装存储历程的新措施的逻辑。连接到数据库、调用存储历程、处置惩罚所有结果集和处置惩罚所有非常是后面要办理的问题。

经由过程构建一个客户机利用或 Servlet,来调用 EJB 组件封装器措施,以测试所做的事情。

头两项是基础编程义务,您可能已经认识。根据所用产品的不合,个别步骤可能会略有不合,然则大年夜多半产品都有对象来供给赞助。例如,假如正在应用 VisualAge for Java 和 DB2,则可以使用“存储历程构建器”来完成步骤 1,以及使用 EJB 开拓特点来完成步骤 2。本文将不集中讲述头两步。然则,另外三步必要具体解说。本文将在一个实际示例的情况下评论争论这些步骤中的每一步。

浏览利用规划

假设必要构建一个利用,该利用支持一家公司的市场营销分部,该分部掩护面向金融的 Web 站点。该站点容许人们注册为客户,跟踪他们的投资总额,以及在电子看护布告板上颁发意见。别的还假设,支持该站点的数据存储在 DB2 的表中。以下代码样本显示若何创建这些表。

在 DB2 中创建样本表的 SQL 语句

create table client (

id int not null primary key,

name varchar(30),

email varchar(30),

phone varchar(12),

regdate date,

mktg char,

constraint check1 check (mktg in (‘y‘, ‘Y‘, ‘n‘, ‘N‘))

)

create table portfolio (

id int not null,

clientID int not null references client,

ticker varchar(10) not null,

cost decimal (9,2),

qty int,

date date,

primary key (id, clientID, ticker)

)

create table boards (

msgno varchar(15) not null primary key,

subject varchar(40),

date date,

clientID int not null references client

)

该数据库还包孕一个分外紧张的存储历程。历程 CLIENTREPORT 供给注册站点用户的综合概要,包括用户投资和他们在看护布告板上评论争论的问题。这个申报还包括客户名称和电子邮件地址,以便在用户提出有关有潜在代价的附加产品或办事方面的建议时,市场营销职员可以与这些用户团结。要在会话 EJB 组件中封装的便是这个历程。

由于此历程可能用多种说话(包括 Java 编程说话)编写,这里就不显示它的完备内容。不管怎么说,源代码确凿不那么紧张,由于您不能假设老是可得到它们。然则,为了奉告您存储历程有什么内容,这里显示了它包括的三个 SELECT 语句:

CLIENTREPORT 存储历程中的 SQL 语句 select name, e-mail from client where id = ?

select id, ticker, cost, qty, date from portfolio where clientid = ?

select msgno, subject, date from boards where clientid = ?

问号表示,该语句将依附运行时来自调用法度榜样的输入,在这种环境下,调用法度榜样必须供给一个代表感兴趣的客户标识的有效数据值。经由过程这些语句,您可以猜出,存储历程将必要一个输入参数(用于客户标识),返回两个输出参数(用于客户名称和电子邮件地址),并返回两个结果集(一个包孕有关客户投资总额的数据,另一个包孕有关客户看护布告板颁发内容的数据)。

改动 EJB 组件的远程接口

现在我们来开始 EJB 组件代码事情。

既然要使封装器措施对 EJB 组件客户机可用,我们必要扩展 bean 的远程接口。将应用一个名为 Analysis 的无状态会话,并包括一个 lookupClient 措施,以用于存储历程封装器。该措施必要一个整数作为输入,以代表要申报的客户标识,它返回一个 DAB CallableStatement 工具(位于 com.ibm.db.* 包中)。将把该历程返回的任何非常转换成 RemoteExceptions(这适用于与 EJB 1.0 兼容的会话 bean)。

以下编码示例显示了 EJB 组件远程接口的改动部分。

EJB 组件远程接口 // Enterprise JavaBean Remote Interface for Analysis session bean

public interface Analysis extends javax.ejb.EJBObject {

// remote interface for our lookupClient method

com.ibm.db.CallableStatement lookupClient(java.lang.Integer clientId)

throws java.rmi.RemoteException;

. . .

}

请留意,假如应用 VisualAge EJB 组件领导,则无需对此进行手工编码。替代措施是,在 bean 的实现类中对此措施编码之后,经由过程菜单项来将该措施提升(promote)到 bean 的远程接口,然后,将自动添加必需的代码。

编码存储历程封装器措施

现在可以集中讲述 bean 实现类本身,将在该实现类中包括调用存储历程的代码,并将其所有输出作为 com.ibm.db.CallableStatement 工具返回。包孕调用 CLIENTREPORT 存储历程的 lookupClient(...) 措施的完备实现。将在后续章节中具体解说每个代码块(参考代码中的注释)的逻辑,以便您更好地舆解若作甚自己的存储历程实现类似的措施。

连接到数据库

让我们更具体地查看此代码的各部分。

在调用存储历程之前,必要建立一个到 DBMS 的连接。有两种措施做获得:应用 1.0 样式的连接,或者应用 JDBC 2.0 样式的 DataSource。在 WebSphere 情况中,平日选用后者,由于它供给连接池(connection pooling),这可以更有效地应用系统资本。出于这种缘故原由,我们的编码模式应用 DataSource。

除了确定要建立的连接类型之外,还应该斟酌要将连接逻辑放在 bean 中的什么地方。有多个选择:

直接放在封装器措施(wrapper method)中

放在私有帮助措施(helper method)中

放在 ejbCreate() 措施中(并将响应的断开逻辑放在 ejbRemove() 措施中)

这些措施的利弊越过了本文的范围。为简单起见,样本代码将所有连接/断开逻辑直接放在措施中。

代码块 1 显示了在应用 VisualAge for Java 3.0.2 和 WebSphere 3.0.2.1 时,若何应用 DataSource 进行连接。我们创建了一个散列表,在此中添补得当于 WebSphere 情况的值,然后建立一个 InitialContext。代码的以下几行使用该初始高低文和 Java 命名和目录接口 (JNDI) 办事,来得到期望的 DataSource 的索引,我们曩昔在 WebSphere 顶用“治理节制台”创建了该 DataSource。本例中的 DataSource 名为 LocalDB2Sample。下一步,应用该 DataSource 来得到一个连接,并向其通报相宜的数据库用户标识和口令。从连接池得到连接之后,可以将该信息供给给 DAB DatabaseConnection 工具,来设置它所需的连接规范。着末,将 autoCommitMode 设置成 false,由于 EJB 组件认真处置惩罚事务治理办事。

测试时,在 VisualAge for Java WebSphere 测试情况中运行应用 DataSource 的 EJB 组件会很方便。有关若何在产品发行版 3.0.2 中这样做的唆使,请参阅 David Zimmerman 所著的 "Creating DataSources in the VisualAge for Java WebSphere Test Environment"(在参考资猜中)。

调用存储历程

建立了连接之后,可以集中讲述若何调用存储历程了。如封装器措施编码示例中的代码块 2 所示,起开创建一个 DAB StatementMetaData 工具,该工具中有存储历程的规范。下一步,定义要履行的 SQL 语句。在这里将要调用 CLIENTREPORT 历程,该历程必要一个输入参数(用于客户标识)和两个输出参数(用于客户名称和电子邮件地址)。下一步,将参数添加到规范中。对付每个历程参数,都指定了参数名,其数据类型及其参数模式。

代码块 3 创建即将履行的 DAB CallableStatement 工具。CallableStatement 代表可用来履行存储历程的 SQL。创建竣工具之后,将其元数据设置成在代码块 2 中指定的形式。然后将 DatabaseConnection(在代码块 1 中创建)与该 CallableStatement 关联。

下一个义务很简单:必要履行 CallableStatement 工具,这将使 DBMS 运行存储历程。然则,在这样做之前,必须经由过程 EJB 客户机利用法度榜样,将历程的输入参数设置成传入措施的值。代码块 4 中显示了这种逻辑。

检索存储历程的输出并返回到调用法度榜样

在封装器措施编码示例的代码块 5 中,将检索存储历程返回的输出参数。想起来了吗?这些参数代表 Web 站点客户的名称和电子邮件地址。然则,不必要显式地检索存储历程返回的结果集。(这些结果集包孕有关客户投资总额和看护布告板颁发信息的数据)。您可能要问:为什么会这样呢?

某些 DBMS 要求,在得到任何输出参数值之前,要从存储历程返回的结果集检索所有必要的值。因为这种要求,在经由过程 getParameter() 措施进行分外哀求之前,CallableStatement bean 不从数据库得到任何输出参数,由于何时从结果集检索数据是由用户节制的。缺省环境下,在履行存储历程之后,将自动检索结果集,并将其存储在高速缓存中。然则,必须显式检索输出参数,并将其存储在高速缓存。

检索完输出参数之后,将 DAB CallableStatement 返回给 EJB 组件的调用法度榜样。该工具现在包孕历程返回的所有输出(包括结果集),和赞助调用法度榜样精确阐发工具语法的适当的元数据。当我们查看调用会话 bean 封装器措施的样本客户机利用法度榜样时,将看到若何去做。

假如您认识 JDBC,可能会问:为什么不在此代码块中显式发出 commit 语句。确凿,假如应用的是 JDBC 1.0 样式的连接,可能必要(否则,当在 "finally" 块中关闭数据库连接时,将逆序规复所做的事情)。然则,应用 DataSource 并吸收 WebSphere 缺省的 EJB 组件属性 (TX_REQUIRED),WebSphere 将自动为我们的事情供给事务治理。是以,不再必要显式的 commit 语句。

处置惩罚非常与关闭打开的资本

当然,在履行会话 bean 时可能会掉足。是以,必要供给非常处置惩罚。代码块 6 包括得当于与 EJB 1.0 兼容的 bean 的简单非常处置惩罚法度榜样。它只是捕获碰到的任何非常,包括一个适当的差错消息,并将非常作为新的 RemoteException 抛回给调用法度榜样。

别的,该代码块还包孕一个 "finally" 块,以确保关闭所有打开的资本。在这里,开释任何与 CallableStatement 工具关联的资本。下一步,撤除在事情中所用的任何对连接的 DAB 引用。着末,确保关闭 WebSphere 连接。

构建客户机利用法度榜样

构建了 EJB 封装器措施之后,该集中讲述客户机利用法度榜样了。与 EJB 组件一样,首先展示客户机利用法度榜样的完备代码样本。然后,将具体讲述个别代码块。

这里显示的客户机利用法度榜样 -- ClientAnalysis -- 应用 RMI/IIOP 与 EJB 组件通信。其事情很简单:创建会话 bean,调用它的 lookupClient(...) 措施,处置惩罚该措施返回的 DAB CallableStatement 工具,然后撤除 bean。将该利用法度榜样编写成处置惩罚 CallableStatement 的通用客户机,即,假设事先不知道有关 CallableStatement 内部布局的任何信息。相反,我们严格依附此中包孕的元数据,来阐发工具的语法,并应用其相关组件,如历程返回的输出参数和结果集。这种措施演示了通用的编码模式,可以在处置惩罚 CallableStatement 的任何利用法度榜样中应用。就这样,它弥补了在无状态会话 EJB 组件中对封装存储历程所用的通用编码模式。

创建 EJB 组件并调用其封装器措施

客户机利用法度榜样的代码块 1 以 main(...) 措施开始。它指定感兴趣的客户标识,并调用一个私有帮助措施,来得到正在应用的会话 EJB 组件。履行完 bean 之后,调用 lookupClient(...) 措施。这是封装 CLIENTREPORT 存储历程并返回 DAB CallableStatement 的措施。

必要具体讲述私有帮助措施 -- createEJB()。由于 EJB 组件创建事情可能会根据所用的 Web 利用法度榜样而略有不合,以是,选择将这个事情隔离成零丁的措施。分外是,因为与该高低文相关的特定属性将会改变,以是,得到 JNDI InitialContext 的措施可能不合。

该 createEJB() 措施创建一个散列表,然后用得当于软件情况的值添补。下一步,创建一个新的 InitialContext 工具,该工具用于经由过程 JNDI 办事得到对 EJB 组件的远程引用。由于从 JNDI 高低文返回 JNDI(这是在 IIOP 之上应用 RMI 的编码需求),以是,限定了该远程引用。得到 EJB 组件宿主之后,创建一个无状态会话 bean,然后将其返回给客户机利用法度榜样的 main 措施。

处置惩罚返回的工具

客户机利用法度榜样的代码块 2 处置惩罚 EJB 组件返回的 DAB CallableStatement 工具。首先定位与 CallableStatement 关联的根元数据工具。由于 CallableStatements 可以得到多个结果集,以是,多个 StatementMetaData 工具可以链接在一路,并包括在 CallableStatement 中。而链的根总包孕描述 SQL 语句的元数据和相关参数,是以,这便是我们的开始之处。这容许我们得到 CallableStatement 中包括的参数数目。返回的数目将包括历程的所有 IN、INOUT 和 OUT 参数。经由过程应用轮回,可以处置惩罚所有参数并打印每个参数的相关信息,包括参数名、响应的 Java 类和模式(指明 IN、INOUT 或 OUT 模式的数字)。

下一步,查当作果集并处置惩罚它们。首先,确定 CallableStatement 工具中包括的结果集数目。经由过程应用轮回,可以得到每个用 DAB SelectResult 工具表示的结果集。然后,应用另一个私有帮助措施 processRS(...) 来处置惩罚结果集。processRS(...) 措施确定通报给 SelectResult 并包孕在此中的行和列的数目。假设有一些行存在,它应用嵌套轮回来打印有关所有行中的所有列的信息。该信息包括列名和它的值。

今朝为止,客户机利用法度榜样的事情险些完成。代码块 3 撤除会话 bean,打印一行注解已完成,然后终止。当然,在代码块 3 之后的代码处置惩罚任何碰到的非常。在这里,只打印一个客栈跟踪。

总结

盼望您已理解会话 EJB 组件若何使用封装在旧有 DBMS 存储历程中的商业逻辑。这样做的其它可能的好处包括:削减 EJB 办事器和 DBMS 之间的收集通信量,前进临盆力,以及低落总体软件掩护资源。假如遵照本文中列出的编码模式,则无论与历程相关的参数或结果集若何,您都可以将任何类型的存储历程作为措施封装在无状态会话 bean 中。而且,您将可以应用通用编码模式来调用任何这样的 EJB 组件,并处置惩罚它返回的工具,而不必事先知道该工具的内部布局。

参考资料

Bontempo、Charles J. 和 Cynthia Maro Saracco 所著的 Database Management: Principles and Products, Prentice Hall, 1995, ISBN 0-13-380189-6。该书评论争论了数据库治理系统的根基,并简述了不合商业产品中供给的功能。

Data Access Beans Javadoc 描述了本文所评论争论的数据造访 Bean 的 API。该书可在 VisualAge for Java 联机文档中得到。在运行产品时,选择赞助 -> 参考资料 -> IBM API -> 数据存取 Bean -> com.ibm.db 包。

Date, C. J. 所著的 An Introduction to Database Systems, Seventh Edition, Addison-Wesley, 1999, ISBN 0-20138-590-2。该书评论争论了数据库治理系统的根基,并供给有关关系数据模型的具体信息。

DB2 产品手册

"Enterprise JavaBeans Specification" 的最新版本,可下载。

"JDBC API Specification" 的最新版本,可下载。

Monson-Haefal, Richard 所著的 Enterprise JavaBeans, O‘Reilly and Associates, 1999, ISBN 1-56592-605-6。该书描述 EJB 编程根基,并供给大年夜量编码示例。

Picon Joaquin 和 Patrizia Genchi、Maneesh Sahu、Martin Weiss、Alain Dessureault 所著的 Enterprise JavaBeans Development Using VisualAge for Java, IBM 红皮书,1999 年 5 月。该红皮书供给有关用 VisualAge for Java 开拓不合种类 EJB 组件的循规蹈矩唆使。请走访 www.ibm.com/redbooks,并搜索 SG24-5429。

Saracco、Cynthia Maro 所著的 "Leveraging DBMS Stored Procedures through Enterprise JavaBeans," IBM 技巧申报 03.723,2000 年 8 月。该申报供给十分具体地评论争论了本文所述的主题,还重点评论争论了设计问题及其利弊。可从 Database and Data Management 白皮书 或 VisualAge 开拓者场地 得到

Saracco、Cynthia Maro 所著的 Universal Database Management: A Guide to Object/Relational Technology, Morgan Kaufmann Publishers, Inc., 1998, ISBN 1-55860-519-3。该书描述了关系 DBMS 供应商已经集成到,或可能要集成到其产品中的面向工具扩展。它供给了大年夜量 SQL 示例。

Ueno、Ken 和 Tom Alcott、Jeff Carlson、Andrew Dunshea、Hajo Kitzhofer、Yuko Hayakawa、Frank Mogus、Colin D. Wordsworth 所著的 WebSphere V3 Performance Tuning Guide,IBM 红皮书,2000 年 3 月。该红皮书为 WebSphere 用户供给调剂机能的技术。请走访 www.ibm.com/redbooks,并搜索 SG24-5657。

联机形式的 VisualAge for Java 产品手册(与产品一路供给),以及位于 VisualAge 开拓者场地网站的产品信息。

联机形式的 WebSphere 产品手册(与产品一路供给),以及可从 Web 利用法度榜样办事器 Web 站点得到的产品信息。

White、Seth 和 Maydene Fisher、Rick Cattell、Graham Hamilton、Mark Hapner 所著的 JDBC API Tutorial And Reference, 第二版, Addison-Wesley, 1999, ISBN 0-201-43328-1。该书描述了 JDBC 2.0,并供给大年夜量编码示例。

Zimmerman 和 Daniel 所著的 "Creating DataSources in the VisualAge for Java WebSphere Test Environment," 经由过程 VisualAge 开拓者场地颁发的技巧文章,2000 年 2 月。该文章描述应用版本 3.0.2 的 VisualAge 开拓职员若何创建和造访 DataSource。要检索该文章,请走访 VisualAge 开拓者场地网站,并在该站点的 Articles 部分搜索 Zimmerman。

谢谢

谢谢 Becky Nin,在我写这篇文章时,她为我供给了赞助。

您可能还会对下面的文章感兴趣: