• 沒有找到結果。

实体 EJB 的开发技术之一 CMP EJB

第 3 章 EJB 技术进阶

3.1 实体 EJB 的开发技术之一 CMP EJB

第 3 章 EJB 技术进阶

在上一章中 我们已经介绍了EJB 的基础知识 还详细描述了 Session EJB 的开发 运行和测试技术 在本章 我们将继续介绍EJB 的开发技术 但是重点将转移到实体 EJB 的开发技术上 本章需要重点掌握的内容有

z CMP 类型的实体 EJB 的开发

z BMP 类型的实体 EJB 的开发

z 利用BMP 类型的实体 EJB 封装数据源

3.1 实体 EJB 的开发技术之一 CMP EJB

在上一章中我们已经提到过 EJB 技术规范支持两种类型的 EJB 对象 它们分别是 Session EJB(会话 EJB)和 Entity EJB(实体 EJB) 第 3 章所开发的 EJB 组件属于会话 EJB

Session EJB(会话 EJB)是短暂存在的对象 它同样运行在服务器端 并执行一些应用 逻辑处理 它的实例对象由客户端应用程序建立 并仅能够被创建它的应用程序所使用 其保存的数据需要开发者编写程序来管理 Session EJB 支持事务属性 但是 当系统因为 某种特殊的不可预见的原因崩溃或者关闭后 Session EJB 的状态 数据不会再被系统恢复 Session EJB 的这种特性十分类似于 Page Scope 类型的 JavaBeans 组件对象

Entity EJB(实体 EJB)是持久运行的 EJB 对象 由某个客户端应用程序创建 但是可以 被其他对象或者其他的应用程序调用 与Session EJB 不同 Entity EJB 必须在建立时制定 一个惟一的标识 并提供相应的机制允许客户应用程序根据 Entity EJB 标识来定位 Entity EJB 的实例对象 多个用户可以并发访问 Entity EJB 事务之间的协调工作由 EJB Container 来完成 读者应当注意 Session EJB 只能够被创建它的应用程序所调用 所以不存在事务 协调的问题 Entity EJB 支持事务处理 当系统关闭时 也可以恢复关闭以前的状态 包括 EJB 对象所包含的数据在内 EJB 规范中定义了两种管理 Entity EJB 的持久性模型 即 Beans Managed Persistence(Beans 自管理方式 简称为 BMP)及 Container Managed Persistence (容 器代管理方式 简称为CMP) BMP 管理方式是由 EJB 对象自己来管理持久性 它需要 EJB 开发者来编写数据库或应用程序的处理逻辑 并加入到 EJB 对象类(EJBObject Class)的 ejbCreate() ejbRemove() ejbFind() ejbLoad()和 ejbStore() Finder 等方法中 CMP 管理 方式是将EJB 持久性管理交给 EJB Container 来完成 开发者不用过多操心 开发者一般要 在EJB 对象的 Deployment Descriptor(部署描述符)中的 Container Managed 属性中指定 EJB 实例对象的持久性作用域 当使用CMP 模式时 开发者不需要知道 Entity EJB 如何存取数 据源 开发者也很少需要参与复杂 烦琐的编码工作 不过CMP 模式的实体 EJB 功能比 较单一 使用起来不灵活 扩展起来比较难 而采用BMP 模式 那就需要开发者事必躬亲 对每一个细小的问题都必须考虑周到 但是BMP 模式的实体 EJB 开发起来很灵活 开发 者有很大的自由度 可以定制复杂的处理逻辑 扩展起来也比较容易 在实际的开发过程



第 3 章 EJB 技术进阶

中 如果需要使用实体 EJB 那么比较单一 固定的任务可以交给 CMP 模式的实体 EJB 完成 而灵活 复杂的系统最好还是采用BMP 模式的实体 EJB 读者需要注意的是 在会 话EJB 中没有 CMP 与 BMP 模式之分 只有 Stateless 与 Stateful 之分

下面我们首先介绍CMP Entity EJB 的开发方法 3.1.1 CMP EJB 简介

CMP 模式的实体 EJB 非常简单 因为有很多的细节问题我们都不需要去关心 EJB Container 会自动实现它们 例如 EJB 类中定义的 ejbCreate() ejbRemove() ejbPassivate() ejbLoad() ejbStore() getXXX() setXXX() 等 方 法 还 有 Home 接 口 中 声 明 的 findByPrimaryKey() findAll()等方法 我们只需要简单地声明它们 或者简单地返回 具 体的实现要依靠EJB Container 还有一个更为重要的问题 那就是 DataSource 在 CMP 模式下面 我们根本就不需要理会DataSource 在哪里 DataSource 如何与实体 EJB 绑定在 一起 实体 EJB 如何存取数据 如何 Load 如何 Store 如何 Create 还有事务的问题 还有持久性的问题 还有并发执行的问题等等 所有的问题都归EJB Container 管理 开发 者不用费半点心思 我们只要把Home Interface Remote Interface EJB 类 部署描述符做 出来 利用EJB Deploy 工具就能够自动生成完备的 可以完成上述任务的 EJB Container 怎么样 是不是很轻松 很简单呢?下面我们就来看看如何利用 JBuilder4 开发一个 CMP 模 式的实体EJB

3.1.2 创建 EJB 工程

我们还是按照上一章的方法 首先利用 JBuilder4 建立一个 EJB 的框架架构 然后在 这个基础之上进行第二次开发 在开发CMP Entity EJB 之前 我们同样要做好配置开发环 境的工作 具体来说 就是配置好IAS 服务器和 JBuilder4 关于配置的方法 读者可以参 考第2 章的介绍 因为我们在上一章已经做好了配置工作 所以在这里就把这一步给掠过 了 不过读者最好还是从头检查一遍开发环境 开发过程中出现的问题多半是由于开发环 境没有配置好而造成的

配置好开发环境以后 我们还有一步额外的工作要做 那就是配置JDBC 数据源 实 体EJB 的主要作用就是映射数据库的结构 并提供一个间接访问数据库中数据的方法 所 以我们在开发实体EJB 之前 必须首先指定 JDBC 数据源

那么如何指定JDBC 数据源呢?请按照下面的步骤去做

1 创建一个数据库 我们所使用的数据库系统是 MS SQL Server 7.0 至于数据库 的结构 请参考附录4 ODBC 数据源的名称为 test

2 启动 JBuilder 选择 Tools JDBC Explorer 将出现如图 3.1 所示的窗口 3 在 JDBC Explorer 中 选择 File New…. 出现一个新窗口 在这个窗口中 我 们指定JDBC Driver 为 sun.jdbc.odbc.JdbcOdbcDriver 读者可以改为其他的 JDBC Driver JDBC URL 为 jdbc:odbc:test(因为 ODBC 数据源的名称为 test) 读者也可以改为其他的 JDBC URL 结果如图 3.2 所示

4 在图 3.2 中 单击 OK 出现了如图 3.3 所示的窗口 我们输入的用户名为 sa 密码为空 然后单击OK 按钮 那么 JDBC Explorer 程序将试图连接到数据库中



第一部分 JSP 技术与 J2EE 技术

3.1 JDBC Explorer 的窗口

3.2 创建新的 JDBC DataSource

3.3 输入数据库的用户名和密码

5 在图 3.3 中 单击 OK 按钮之后 如果 JDBC Explorer 连接数据库系统成功 那 么JDBC Explorer 的主窗口将如图 3.4 所示 我们应该逐个展看窗口左侧的视图 明了数据 库的字段结构 同时也可以在右侧的窗口中输入SQL 语句 并执行它 改变数据库的结构 或者更新里面的数据



第 3 章 EJB 技术进阶

3.4 利用 JDBC Explorer 查看数据库的结构

6 关闭 JDBC Explorer 这时候程序提示你是否保存所做的改变 你应该选择保存 要不然你所做的一切工作都白费了 又得从头再来

配置好JDBC DataSource 以后 我们的下一步就是创建一个实体 EJB 工程 读者请跟 着下面的步骤一步一步尝试 一定会成功的

7 在 JBuilder4 的主运行界面中 选择 File New… Enterprise Tab Empty EJB Group JBuilder4 会自动创建一个新的 Project 我们把这个 Project 的名字指定为 JDBCTest 如图3.5 所示

3.5 JBuilder4 的 Project Wizard



第一部分 JSP 技术与 J2EE 技术

8 创建好 JDBCTest Project 以后 Empty EJB Group Wizard 会自动运行 我们指定 这个EJB Group 的名字为 JDBCTest 包含此 EJB 组件的 jar 文件名为 JDBCTest.jar 如图 3.6 所示

3.6 JBuilder4 的 Empty EJB Group Wizard

9 创建好 EJB Group 以后 下面该创建一个 Entity EJB 了 在 JBuilder 的主运行界 面中 选择File New… Enterprise Tab EJB Entity Bean Modeler 然后单击 OK 按钮 如图3.7 所示

3.7 创建 EJB Entity Bean Modeler

10 在图 3.7 的窗口中 单击 OK 按钮之后 出现如图 3.8 所示的对话框 确保 Available EJB groups 下拉列表中选的是 JDBCTest.ejbgrp 然后单击 Next 按钮



第 3 章 EJB 技术进阶

3.8 JBuilder4 的 EJB Entity Bean Modeler Wizard 11 接着上一步 将出现如图 3.9 所示的对话框

3.9 设定 JDBC DataSource

在图3.9 中 我们需要点击 Choose Existing Connection…按钮 选择已经存在的 JDBC 数据源 也就是一开始就设定的那一个 JDBC 数据源 jdbc:odbc:test 然后在 Username



第一部分 JSP 技术与 J2EE 技术

处填入sa 让 Password 空着 JNDI name 保持 DataSource 不变 单击 Next 按钮 进入下 一步

12 在这一步中 设定 Entity EJB 需要映射的 Table JBuilder4 会根据 Table 的字段 名字 自动产生setXXX()方法和 getXXX()方法 jdbc:odbc:test 数据源所对应的数据库一共 有 4 个用户表 分别是 goods 表 tbuser 表 tborder 表 dtproperties 表 我们选定 goods 表作为Entity EJB 映射的 Table 方法是在左侧的窗口中 选定需要映射的 Table 然后单 击 > 按钮 那么这个 Table 的名字就会移到右边的窗口中 这样就可以了 如图 3.10 所示

3.10 选定 Entity EJB 所映射的 Table

13 在图 3.10 的对话框中 单击 Next 按钮 进入一个新的对话框 不要做任何改 动 再次单击Next 按钮 将显示如图 3.11 所示的对话框 在图 3.11 的对话框中 我们将 设定Entity EJB 的 Primary Key 亦即主键 在 Entity EJB 的 Home Interface 中 声明了 findPrimaryKey()方法 利用这个方法 可以获取特定的 Remote 对象 我们所说的主键 其实就是 Table 的某一个或者某几个特定的字段 但是这些字段的值必须是唯一的 亦即 在数据库的记录中 不能够有相同的值 如果某一个字段被设为主键 那么JBuilder4 只会 为它自动产生getXXX()方法 而不会产生 setXXX()方法 因为主键是标识 Entity EJB 的唯 一的标志 当然不能够被改动 而且主键的值必须是唯一的 不被设定为主键的字段既可 以有setXXX()方法 也可以有 getXXX()方法 其实 Entity EJB 的主键与数据库的主键有一 定的相似之处 Entity EJB 就相当于记录集中的一个行纪录

在图3.11 的对话框中 我们选定字段 id 作为此 Entity EJB 的主键 这只需要在 id 字 段前面的那一个小框中打勾即可 选中id 字段以后 单击 Next 按钮 进入下一步

14 在图 3.11 中 单击 Next 按钮以后 会进入如图 3.12 所示的对话框 JBuilder4



第 3 章 EJB 技术进阶

根据Table 的名字(goods)自动生成这个 Entity EJB 的 Home Interface Remote Interface EJB Class JNDI 服务的名字 我们可以修改这些名字 把它们改成希望的值 在这个例子中 Bean 的名字为 Goods JNDI 服务名为 Goods Home Interface 的名字为 jdbctest.GoodsHome Remote Interface 的名字为 jdbctest.GoodsRemote EJB Class 的名字为 GoodsBean 主键的 类型为int 也就是 goods Table 的 id 字段 一切都设置好以后 清单击 Next 按钮 进入下 一步

3.11 选定 Entity EJB 的主键

3.12 设定 Entity EJB 的 Home Remote Interface 和 EJB Class 的名字



第一部分 JSP 技术与 J2EE 技术

15 在图 3.12 的对话框中 单击 Next 按钮 将进入如图 3.13 所示的对话框 在该 对话框中 我们将设定Goods EJB 的模式是 CMP 还是 BMP

3.13 设定 Entity EJB 的模式

如图3.13 所示 我们选中了 Container managed persistence 还选中了 Generate findAll()

如图3.13 所示 我们选中了 Container managed persistence 还选中了 Generate findAll()