posts - 66,  comments - 11,  trackbacks - 0

    实体Bean是持久化对象,它能够存储到持久化存储源中。实体Bean是EJB编程模型中最为重要的利器之一。
    将对象映射到RDBMS的技术称之为对象-关系映射。它能够实现内存对象同关系数据的相互转换。O/R映射器能够将Java对象映射到任意RDBMS模式。比如简单的O/RMapping引擎能够将Java类映射成SQL表定义。Java语言提供的对象序列化功能比O/RMapping简单多了。O/RMapping是更加复杂、成熟的对象持久化机制。通过将Java对象分解成关系数据,应用便能够查找到所需的数据了。
    通过如下两种方式能够完成Java对象到关系数据的映射。其一,通过硬编码实现O/RMapping.其二,借助于O/RMapping产品,自动完成映射过程,比如:Hibernate.
    对于任何成熟的、基于OO多层部署的企业应用而言,总可以划分出2种截然不同的组件类型。1、应用逻辑组件,2、持久化数据组件。会话Bean和实体Bean的最大区别在于实体Bean是实体,客户是可以看的到的。因此实体Bean能够独立于客户应用的生命周期。对于实体Bean而言,通过比较它们各自含有的数据便能够区分不同的实体Bean.这意味着客户能够引用单个的实体Bean实例并将它传入到其他应用中,不同的客户可以共享同样的实体Bean实例,这对于会话Bean是办不到的。会话Bean建模过程或者工作流。实体Bean本身就是客户,它就是持久化状态对象。
    实体Bean实例存在几方面的含义:
1、持久化数据的Java表示,即它能够从持久化存储源装载数据到内存中。同时,实体Bean实例能够将装载到的数据存储到实例的成员变量中。
2、通过修改内存中的Java对象可以改变数据的取值。
3、还可以将修改后的数据保存到存储源汇中,从而更新RDBMS中的物理数据。
    实体Bean是持久化对象,它能够长期存在。即使出现了不可恢复的失败,比如应用服务器瘫痪、数据库瘫痪,实体Bean还是能够存活的。原因在于实体Bean只是对底层具有容错行为的持久化存储源中数据的映射,因此,即使极其瘫痪,内存中的实体Bean实例还可以重新构建。在极其重启后,实体Bean实例需要从底层存储源装载数据,并使用获得的数据对实体Bean实例中的各个域进行setter操作。实体Bean比客户会话的生命周期要长。可以认为,数据库中记录存活的时间决定了实体Bean实例的生命周期。
    相同数据往往存在多分物理拷贝,比如内存中的实体Bean实例、实体Bean数据本身,他们都是对RDBMS中数据的拷贝。因此,EJB容器需要提供某种机制实现数据在Java对象和RDBMS间的自动传输。实体Bean的Bean类为此提供了2个特殊方法:
ejbLoad():它能够从持久化存储源中读取数据,并存储到实体Bean实例的域中。
ejbStore():它能够将当前实体Bean实例的域值保存到底层RDBMS中。
那么何时需要完成内存中实体Bean实例和RDBMS中数据的传递和转换,开发者需要知道是谁调用了ejbLoad()和ejbStore(),答案是EJB容器。它们是回调方法,供EJB容器调用。EJB规范要求所有的实体Bean组件必须提供它们。至于读取或存储数据的时机,由EJB容器决定。依据实体Bean实例当前的事务状态,EJB容器会自动计算出需要调用实体Bean实例中的ejbLoad(),ejbStore()方法的时机,这也是使用实体Bean组件的优势之一:开发者不用考虑java对象同步底层RDBMS的问题。

    为了满足大量并发客户访问同一数据的要求,架构师需要借助于实体Bean设计出高性能的访问系统。如下给出一种解决方案:允许多个客户共享同一实体Bean实例。因此,实体Bean实例能够同时服务多个客户。尽管表面上看是可行的,但是对于EJB而言,这是行不通的。原因有亮点:其一,为实现实体Bean实例服务多个并发客户,必须保证实体Bean实例是线程安全的,开发线程安全的代码并不是一件容易的工作,而且经常会出现一堆错我。其二,底层事务系统几乎不可能控制多个线程的并发执行,事务往往同具体的线程绑定在一起。因此,基于上述理由,单个实体Bean实例只能够在单线程环境中运行。对于所有的EJB组件而言,包括会话Bean、消息驱动Bean、实体Bean,它们都是以单线程方式运行的。
    当然,强制要求各个实体Bean实例只能同时服务单个客户,将引入性能瓶颈。由于实例以单线程方式运行,客户需要排队等候实体Bean实例,从而获得对实体Bean实例的调用,这对于大型企业应用而言,是不允许出现的
    为了提供系统性能,EJB容器会实例化同一实体Bean的多个实例。这使得多个客户能够并发同不同实体Bean实例进行交互,而这些实体Bean实例代表了同一RDBMS数据。事实上,这就是EJB容器的运行行为。因此,客户再也不用排队等候实体Bean实例,因为存在多个实体Bean实例了。
    一旦多个实体Bean实例代表了同一RDBMS数据,则引入了另外一个问题:数据瘫痪。如果多个实体Bean实例代表的数据是通过缓存管理的,则需要在内存中拷贝多分缓存中的数据。显然,某些缓存中的数据将变得陈旧,因此会出现很多过期的数据。
    为了实现实体Bean实例的缓存一致性,各个实体Bean实例必须同底层存储元进行同步。EJB容器将通过调用ejbLoad(),ejbStore()方法同步这些实体Bean实例。
    至于实体Bean实例同底层RDBMS数据的同步频率,则取决于事务。事务将各个客户请求隔离起来。借助于事务实现数据同步。

    EJB容器提供的实例池是很有意义的。当然,并不是只有实体Bean才存在实例池。在将实体Bean实例重新分配给不同EJB对象时,会存在一些问题,并要求容器去解决。比如当实体Bean实例被指定给EJB对象时,它可能还持有资源(比如Socket连接)。如果将实体Bean实例放置在实例池中,Socket连接不在需要。因此为实现资源的获取和释放,实体Bean的Bean类需要实现如下2个回调方法:
1、ejbActivate().在将实体Bean实例从实例池中取出来时,EJB容器会自动调用它。该过程称之为激活。进而,EJB容器会将实体Bean实例分配给某EJB对象,并同时获得主键对象。在执行ejbActivate()方法期间,实例需要获得所需的资源,比如Socke,否则,在将实体Bean实例分配给某EJB对象时,无法对资源进行操作。
2、ejbPassivate().在将实体Bean实例放置到实例池中时,EJB容器会调用它。注意,它也是回调方法。这一过程称之为挂起。进而,EJB容器需要从某EJB对象中取回分配于它的实体Bean实例,并将实例的主键对象也收回。在执行ejbPassivate()方法期间,需要释放ejbActivate()执行期间获得的相关资源,比如:Socket.
    一旦实体Bean实例被挂起,不但要释放它持有的资源,还将实例的状态信息保存起来。因此,实体Bean实例最新的状态信息可以从RDBMS中找到了。为了保存实体Bean实例的域信息到RDBMS中,容器要在挂起实例前调用ejbStore()方法。类似的,一旦实体Bean被激活,不但要获得所需的资源,还要从RDBMS装载最新的数据,为了完成数据的读取,EJB容器将在激活实体Bean实例后调用ejbLoad()方法。


 

posted on 2009-11-15 11:46 王永庆 阅读(265) 评论(0)  编辑  收藏 所属分类: EJB学习笔记

只有注册用户登录后才能发表评论。


网站导航:
 
<2009年11月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

常用链接

留言簿(1)

随笔分类

随笔档案

关注blogs

搜索

  •  

最新评论

阅读排行榜

评论排行榜