Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > Java > 全面研读EJB 2.0(2)
【标  题】:全面研读EJB 2.0(2)
【关键字】:EJB,EJB
【来  源】:网络

全面研读EJB 2.0(2)

Your Ad Here 全面研读EJB 2.0(2)

· EJB 2.0 的 CMP 模型

在 EJB 2.0 中,CMP 实体 bean 和持久性管理器之间的新合约,使您能够在实体 bean 中定义更复杂的、可移植性更强的关系,包括 bean 与 bean 之间、bean 与从属对象之间、甚至从属对象与从属对象之间的关系。

持久性管理器是新加入到 Enterprise JavaBeans 部署过程中的。容器厂商,或专长于特定数据库的持久性的厂商,将能提供这种持久性管理器。其思路是将用于管理 bean 关系的机制从容器中分离出来,容器只负责管理安全、事务和资源。这种职责上的分离使不同的持久性管理器能够与不同的容器一起工作。它也使实体 bean 在不同 EJB 厂商之间以及在各种持久性管理器之间具有更强的可移植性。

如果您使用或学习过 Thought Inc. 生产的,能自动为 EJB 1.1 容器生成 BMP(bean 管理的持久性)bean 的产品 CocoBase,则您对持久性管理器工具如何工作就已经比较熟悉了。CocoBase 根据 bean 部署者提供的,从对象到关系的映射信息,为 BMP bean 生成全部数据库访问逻辑。在 EJB 2.0 中,持久性管理器能够根据部署描述符、bean 的抽象持久性方案和部署者完成的工作所提供的信息,生成 CMP 实体到关系数据库的映射。但是,持久性管理器并不局限于关系数据库。也可以为对象数据库以及遗留的系统和 ERP 系统(如 SAP)开发持久性管理器。

为了将持久性管理器从容器中分离出来,必须定义 bean 与持久性管理器之间的合约。这个合约在新的抽象持久性方案中表现出来。此方案是通过部署描述符中一组新的 XML 元素和 CMP 实体 bean 中的一组代码习语定义的。在 EJB 2.0 中,CMP bean 类被声明为抽象类,它的持久性字段和关系字段是使用抽象的读方法和写方法来访问的,而这两种方法的方法特征则映射为 XML 部署描述符中的特定元素。

在部署该 bean 时,您将使用持久性管理器工具,根据 XML 部署描述符和 bean 类,来具体实现此抽象 bean 类及其从属对象类。具体实现将包括数据访问代码,此代码将在运行时将 bean 的状态实际读出和写到数据库中。在运行时,容器使用由持久性管理器工具生成的子类,而不使用 bean 提供者定义的抽象类。

bean 类的继承层次结构

为了使讨论更充实,这里提供一个 CMP 实体的示例,它更具体地说明了抽象持久性方案是如何工作的。

EJB 2.0 中的一个示例 CMP 实体
在 EJB 2.0 中,容器管理的实体 bean 被定义为抽象的,而且它的持久性字段并不在 bean 类中直接定义。作为替代,开发了一种抽象的持久性方案,从而允许 bean 提供者间接地声明持久性字段和 bean 关系。下面是 Employee bean 的一个示例,它使用了新的抽象持久性方案。请注意,该 bean 类中未声明任何持久性字段。

public abstract EmployeeBean implements
javax.ejb.EntityBean {
. // 实例字段
EntityContext ejbContext;
// 容器管理的持久性字段
public abstract void setIdentity(int
identity);
public abstract int getIdentity();
public abstract void setFirstName(String
firstName);
public abstract String getFirstName();
public abstract void setLastName(String
lastName);
public abstract String getLastName();
// 容器管理的关系字段
public abstract void
setContactInfo(ContactInfo info);
public abstract ContactInfo
getContactInfo();
...
}

在此 bean 的 XML 部署描述符中,抽象的持久性方案声明容器管理的各个字段和各种关系。

<ejb-jar>
<enterprise-beans>
<entity>
<ejb-name>EmployeeEJB</ejb-name>
...
<persistence-type>Container</persistence-type>
...
<cmp-field><field-name>identity</field-name></cmp-field>
<cmp-field><field-name>firstName</field-name></cmp-field>
<cmp-field><field-name>lastName</field-name></cmp-field>
...
</entity>
</enterprise-beans>
<dependents>
<dependent>
<dependent-class>ContactInfo</dependent-class>
<dependent-name>ContactInfo</dependent-name>
<cmp-field>street</cmp-field>
<cmp-field>city</cmp-field>
<cmp-field>state</cmp-field>
<cmp-field>zip</cmp-field>
<cmp-field>homePhone</cmp-field>
<cmp-field>workPhone</cmp-field>
<cmp-field>email</cmp-field>
...
</dependent>
<relationships>
<ejb-relation>
<ejb-relation-name>Employee-ContactInfo</ejb-relation-name>
<ejb-relationship-role>
<ejb-relationship-role-name>
employee-has-contactinfo
</ejb-relationship-role-name>
<multiplicity>one</multiplicity>
<role-source>
<ejb-name>EmployeeEJB</ejb-name>
</role-source>
<cmr-field>
<cmr-field-name>contactInfo</cmr-field-name>
<cmr-field-type>ContactInfo</cmr-field-type>
</cmr-field>
</ejb-relationship-role>
<ejb-relationship-role>
<ejb-relationship-role-name>
contactinfo_belongsto_employee
</ejb-relationship-role-name>
<multiplicity>one</multiplicity>
<role-source>
<dependent-name>ContactInfo<dependent-name>
</role-source>
</ejb-relationship-role>
</ejb-relation>
</relationships>
<ejb-jar>

用来描述容器管理的关系的 XML 元素可能变得非常复杂,因为他们必须处理各种关系的对应性和方向(单向的还是双向的)。上面的代码段说明,为了描述 bean 与其从属对象类之间的简单关系,您需要哪些元素。虽然即使是简单的关系也会被转换为冗长的 XML,但所有这些元素都是必需的,以便持久性管理器能够将复杂的对象图映射到数据库中。

虽然用于定义 CMP bean 的抽象持久性方案的 XML 元素是 EJB 2.0 中的 CMP 的主要问题,但为了简洁起见,本文不再提供 XML 示例。作为替代,本文将纯粹依靠 bean 类中必须使用的抽象习语,来说明 EJB 2.0 中的 CMP 背后的基本概念。这些代码习语与 XML 部署描述符中的关系元素一起使用,并由后者定义,所以您不能只有其一而没有另一个,但它们比该方案的 XML 部分较容易理解。

除了 XML 元素之外,抽象的持久性方案还定义了一组习语,它们在声明 bean 类及其相关的对象时必然会用到。用来访问和修改字段的方法是严格定义了的,要求用 set<METHOD> 方法修改持久性字段,而用 get<METHOD> 方法访问它们。这些方法的名称和返回类型由部署描述符中它们相应的 XML 关系元素规定。

实体 bean 类和从属类都遵循相同的抽象持久性方案。下面是如何将 ContactInfo 对象定义为从属对象类的示例。

public abstract class ContactInfo {
// 家庭地址信息
public abstract void setStreet(String street);
public abstract String getStreet();
public abstract void setState(String state);
public abstract String getState();
public abstract void setZip(String zip);
public abstract String getZip();
public abstract void setHomePhone(String phone);
public abstract String getHomePhone();
// 工作地址信息
public abstract void setWorkPhone(String phone);
public abstract String getWorkPhone();
public abstract void setEMail(String email);
public abstract String getEMail();
...
}

从属对象随实体 bean 的存在而存在,随实体 bean 的中止而中止,这是理解从属对象与实体 bean 之间关系的关键。从属对象包含在一个具体的实体中,所以删除这个实体将导致从属对象也被删除。用关系数据库的术语来说,有时这就称为级联删除。

从属对象,如 ContactInfo,用在关系字段中。与实体 bean 形成关系的从属对象技术上称为从属对象类。EJB 客户端应用程序永远不能直接访问从属对象类;这种类不能用作 bean 的远程或本地接口中的参数或返回值。从属对象类只对 bean 类才是可见的。

从属对象类不适合作为远程参数类型,因为它们与 bean 在运行时的持久性逻辑有密切的联系。持久性管理器扩展了抽象的从属对象类,以便能提供一种实现,可用于在运行时管理 bean 的持久性状态。此外,抽象的持久性方案还为数据建模 -- 而不是为那些由企业级 bean 表示的业务概念建模 -- 所以,作为一种设计策略,将抽象的持久性方案对 EJB 客户机隐藏起来是有意义的。

例如,ContactInfo 关系字段中除了 bean 的客户机所需的简单地址信息之外,还包含许多其它信息。虽然您可以使用抽象持久性方案中的从属对象类 ContactInfo(它对 bean 的客户机是隐藏的),但是,您得用其它的对象来把这些数据实际表露给客户机。下面是一个示例,说明了如何对 EJB 客户机隐藏 ContactInfo 从属对象。在此例中,地址信息是通过在 EJB 1.1 的示例中开发的 Address 对象来表露的。

// Employee bean 的远程接口
public interface Employee extends javax.ejb.EJBObject {
public Address getHomeAddress();
public void setHomeAddress(Address address);
public int getIdentity() throws RemoteException;
public void setFirstName(String firstName) throws
RemoteException;
public String getFirstName()throws RemoteException;
public void setLastName(String lastName) throws
RemoteException;
public String getLastName() throws RemoteException;
}
// Employee bean 的 bean 类
public abstract EmployeeBean implements
javax.ejb.EntityBean {
...
public Address getHomeAddress(){
ContactInfo info = getContactInfo();
Address addr = new Address();
addr.street = info.getStreet();
addr.city = info.getCity();
addr.state = info.getState();
addr.zip = info.getZip();
return addr;
}
public void setHomeAddress(Address addr){
ContactInfo info = getContactInfo();
info.setStreet(addr.street);
info.getCity(addr.city);
info.getState(addr.state);
info.getZip(addr.zip);
}
....
// 容器管理的关系字段
public abstract void setContactInfo(ContactInfo
info);
public abstract ContactInfo getContactInfo();
...
}

尽管容器管理的关系字段没有表露给客户机,但您仍然可以从远程接口直接使用容器管理的持久性字段。请注意,用来访问 firstName 和 lastName 的容器管理的持久性字段是在远程接口中使用的。

一个 bean 与各种从属对象类之间可能具有多种不同的关系,它们由这种关系的对应性和方向来定义。Bean 与从属对象类之间可以有一对多和一对一的关系。例如,Employee bean 可能仅有一个 Benefit 从属对象类,但可能有许多 ContactInfo 从属对象类。

public abstract EmployeeBean implements
javax.ejb.EntityBean {
...
public abstract void setContactInfos(Collection
addresses);
public abstract Collection getContactInfos():
public abstract void setBenefit(Benefit benefit);
public abstract Benefit getBenefit();
...
}

与从属对象类的一对多关系既可表示为 java.util.Collection 类型,也可表示为 ava.util.Set 类型(注:在本规范的后续版本中,java.util.Map 和 java.util.List 被视为附加的返回类型),而与从属对象的一对一关系则使用从属对象的类型。

实体 bean 也可以定义与其它实体 bean 的关系。这些关系可以是一对一、一对多或多对多。例如,Employee bean 可能有许多子级 bean,而只有一个配对的 bean。下面的代码段使用抽象持久性方案的方法习语,说明了如何为这些关系建模。该应用程序中,子级 bean 和配对的 bean 都表现为 Person bean。

public abstract EmployeeBean implements
javax.ejb.EntityBean {
...
public abstract void setSpouse(Person manager);
public abstract Person getSpouse();
public abstract void setChildren(Collection
family);
public abstract Collection getChildren();
...
}

与另一个 bean 的一对多关系表示为 java.util.Collection 类型或 java.util.Set 类型,而一对一关系则使用该 bean 的远程接口类型。

从属对象本身与同一个 bean 中的其它从属对象之间可以有一对一、一对多和多对多的关系。此外,从属对象与其它实体 bean(除其父级 bean 之外)也可以有一对一、一对多的关系。下面的示例显示,Benefit 从属对象类与 Salary 从属对象(一种报酬计算程序)之间怎样具有一对一的关系,而与 Investment bean 又怎样具有一对多的关系。

public abstract class Benefit {
public abstract void setSalary(Salary salary);
public abstract Salary getSalary();
public abstract void setInvestments(Collection
investments);
public abstract Collection getInvestments();
}


在部署时,部署者将使用持久性管理器工具来具体实现这个 bean 类及其从属类。这些具体实现将在运行时保持各种关系,并使各 bean 实例的状态与数据库同步。容器将在运行时管理持久性实例,从而提供一种强健的环境,其中具有自动的访问控制和事务控制。

bean 也可以定义从属对象的值,这些对象是可序列化的对象,如 EJB 1.1 示例中的 Address 对象。这些值通过序列化而变为持久的,它们并不形成与 bean 的关系 -- 它们是严格的容器管理的持久性字段。

容器与持久性管理器之间也已经定义了一个合约,使持久性管理器可以获得事务的句柄,并访问由该容器管理的数据库连接池。这个合约稍嫌宽松,将来还需要使其更为严格,但它是允许持久性管理器跨 EJB 容器移植的基础。容器和持久性管理器之间合约的细节已超出了本文的范围。

除了通过抽象持久性方案定义持久性之外,EJB 2.0 还提供了一种新的查询语言,用来说明持久性管理器应该如何实现 CMP 中的各种查找方法。

(未完待续)
全面研读EJB 2.0(3):【上一篇】
全面研读EJB 2.0(1):【下一篇】
【相关文章】
  • 全面研读EJB 2.0(3)
  • javabean与ejb的区别
  • J2EE 组件开发:会话EJB
  • EJB 异常处理的最佳做法(1)
  • EJB 异常处理的最佳做法(2)
  • EJB 体系结构的历史和目标
  • JBuilder7+Weblogic7+mysql开发EJB的配置
  • HTTP会话对象 VS 有状态EJB
  • 用Jbuilder 7开发EJB例程-开发Session Bean源码
  • J2ee之EJB种类介绍
  • 【随机文章】
  • 关于Access数据库的问题
  • AIX僵死(defunct)进程故障分析
  • 高级表单验证(转)-针对多次提交表单
  • XML 名字空间
  • 用Factory Method模式扩展MyMSDNTVLibrary
  • 创建一个Registry Server
  • 在GD中输出汉字的函数的改进
  • Ruby简介
  • jbpm知识点——ProcessState2
  • Oracle Select语句处理的Bug
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.