表格型的关系型数据库与树型java对象之间的映射问题是一个至今争论不休的问题,好在现在已经有了一些好的解决方案。在本文中,我们将介绍ejb技术是怎样用自已特定的方式来解决这个问题的。
只要是涉及到保存及查询信息 ,那绝大多数应用程序都需要与关系数据库打交道。但由于关系数据库与java对象在结构上有着本质的区别,关于它们之间的映射关系对于那些java开发者们来说,是一个很令人头痛的问题。关系型数据库是以表格方式存储数据的,而java对象是以树型方式表现的。这种类型上的不匹配引发了各种各样的对象持久化解决方案,用来缩小关系世界与对象世界之间的鸿沟。ejb框架正是这种解决方案之一。
对象的持久性
目前有很多不同的工具出现,使得开发人员可以将java对象转化为数据库中的字段或记录,或者将数据库中的字段或记录还原为java对象。这些处理涉及到要将树型的java对象序列化到数据库中,反之亦然。此工作的核心是怎样在保证最小性能损失的前提下,来完成这项工作。
ejb框架提供了这样一个对象持久化机制。我们将在本文中讨论这种机制,但首先我们还是对ejb构架作一个全面的认识。
企业级javabeans(ejb)
ejb技术可以这样定义:它是一个基于java服务端的,为分布式应用提供的一个可复用的组件框架。所有的商业逻辑、部署定义、对象持久性都由这个框架统一管理,ejb框架的一些特色如下:
? ejb是一种运行在服务端环境下的java对象。
? ejb能分布在不同的机器上进行远程访问,但对客户端来而言,调用ejb与调用本地javabean一样方便。
? ejb容器对ejb进行统一管理。
尽管企业级javabean的名字与普通javabean在命名上有些相像,但它们在设计上有着本质上的区别。为了能让你更清楚地认识到这点,我们最好先了解一下ejb的基本概念、几种ejb组件模式和其配置环境。
ejb的运行环境
从本质上来说,ejb只是实现了特定接口的普通java对象,但这个对象必须运行在一个特定的环境:ejb容器中。如果脱离了ejb容器,ejb是无法运行的。ejb与ejb容器之间的关系有时候被称为"反向调用"?d?d或者叫"好莱坞原理"(别联系我,到时候我会给你打电话的)。
ejb容器是一种用来管理ejb的运行时环境。它容纳并管理不同类型的ejb,这与java servlet容器管理servlet有些类似。ejb容器负责初始化ejb,并给其提供系统级的服务。
当客户端程序要调用某一个ejb时并不直接与ejb打交道,客户端与ejb被容器隔离起来。
ejb容器提供的服务
当开发者创建一系列的类与接口,用来组成一个ejb时,容器会为他们提供如下的系统级服务:
? 事务处理
? 安全管理
? ejb的持久化管理
? ejb的远程访问
? ejb的生命周期管理
? 数据库连接池
? ejb的实例池管理
由于ejb容器负责为ejb提供这种底层服务,使得一个ejb开发者只需关注具体应用的商业逻辑,从而减少了很多不必要的麻烦。
ejb的类型
ejb规范定义了以下三种不同类型的ejb类型:
? 消息驱动ejb(mdb)
? 会话ejb
? 实体ejb
当客户端与会话ejb或实体ejb交互时,它们的通信方式是同步通信。而消息驱动ejb(mdb)则只与jms进行交互,它相当于jms中的一个发布/订阅主题。
消息驱动ejb
消息驱动ejb工作在异步通信模式下。一个消息驱动ejb充当一个消息侦听者的角色,它侦听从jms的发布/订阅主题中传来的消息。
ejb容器管理着消息驱动ejb的生命周期,然而与会话ejb和实体ejb不同之处在于客户端并不能直接调用它的方法。消息驱动ejb是通过一个名为onmessage的回调函数来接收客户端的消息的。
会话ejb
会话ejb的特点是不能同时被多个客户端共享。当客户端调用会话ejb的方法时,先经过ejb容器处理,然后再由容器对会话ejb进行调用。会话ejb处理开发者编写商业逻辑,容器再将处理结果返回给客户端。会话ejb不能在多个会话中持久保存。它分为两种类型:有状态的会话ejb和无状态的会话ejb。
有状态的会话ejb
当一个客户端与某一个有状态的会话ejb开启一个会话时,这个ejb为客户端维护了一个会话状态。这暗示着客户端向此ejb发出不同的调用请求之间保证ejb的成员变量值不会丢失。
一旦客户端结束与有状态的会话ejb的交互后,ejb容器会自动销毁它。于是整个会话结束,并且此有状态的会话ejb所保存的状态数据会全部丢失。
无状态会话ejb
无状态会话ejb并不为客户端保存任何状态数据。你可以这样认为:客户端每次对无状态会话ejb的调用都会产生一个新的ejb实例,因此所有的状态信息都不会保存。 同样,ejb容器也不会持久化任何无状态会话ejb,因此开发者必须意识到客户端与无状态会话ejb之间进行交互时,所有的状态数据都是临时的。无状态会话ejb的这种特性使得容器可以重复地使用它的实例,因此无状态会话ejb能得到比有状态会话ejb更好的性能。
实体ejb
实体ejb表达的的是一种持久存储的商业逻辑,通常存储于关系型数据库中。实体ejb与关系型数据库有如下的相似之处:
? 实体ejb是持久的?d?d它可以在应用程序的生命周期之外存在,甚至可以在ejb容器的生命周期以外存在。
? 实体ejb允许共享访问?d?d多个客户端可以共享同一个实体ejb,而容器负责管理它们之间的同步。
? 实体ejb有主键?d?d主键用来确定实体ejb的一个唯一实例,利用它可以找到一个特定的持久化实体。
? 实体ejb有事务的概念?d?d由于客户端能并发访问并修改它的数据,因此事务管理是非常重要的。事务管理属性被显示地定义在部署描述文件中,而容器负责管理事务的边界。
要实现对象-关系映射,那实体ejb必须能提供插入、更新、查询、删除的操作。而用于管理实体ejb对象与数据源之间的映射的过程被称为持久化。换句话说,持久化是一个将信息写入外部数据源的一个过程。ejb规范定义了实体ejb的两种持久化方式:bean自身管理的持久化(bmp)和容器管理的持久化(cmp)。
bean自身管理的持久化(bmp)
如果你选用bmp,那你必须在你的代码中负责维护所有的持久化发。那么所有的数据层访问代码都必须由开发者来完成,这种方式能带给开发者更大的灵活性。
容器管理的持久化(cmp)
如果你选用cmp,那你不用编写数据层访问代码,ejb容器将会为你管理所有的持久化。因此,数据层访问代码与数据源之间是松耦合的。这能减轻开发者的代码编写量,并且使得cmp能部署到不同厂商的应用服务器中,也不必关心具体的数据源。
ejb部署与运行时环境
我们将以jboss3.0.2作为ejb部署与运行时环境的服务器。我们将设计一个简单的web应用,它允许创建用户帐号,用户通过访问web浏览器,而web浏览器通过调用一个servlet来取得这个帐号,这个servlet与一个实体ejb相互通信。当这个作为控制器的servlet接收到客户请求后,它将这个请求转化一个业务请求并向业务服务层调用相应的服务。业务服务层使用一个或多个实体ejb来从数据层中取得或保存数据。
编写并部署一个实体ejb
以下四个步骤是开发一个实体ejb的典型流程:
1. 为你的实体ejb编写相应的类及接口
2. 编写相应的部署描述文件
3. 将实体ejb及相应的部署描述文件打包成为一个jar文件
4. 部署此实体ejb
一个实体ejb至少由以下三个类(接口)组成:
组件接口?d?d在本例中我们只考虑从同一jvm虚拟机中访问实体ejb,因此我们需要继承javax.ejb.ejblocalobject接口。
2. package com.jeffhanson.datatier.ejb;
3.
4. import javax.ejb.ejblocalobject;
5.
6. public interface localuser extends ejblocalobject
7. {
8. public string getuserid(); //主键
9. public string getfullname();
10. public string setaddress(string address);
11. public string getaddress();
12. public string setcity(string city);
13. public string getcity();
14. public string setstate(string state);
15. public string getstate();
16. public string setzip(string zip);
17. public string getzip();
}
18. home接口?d?d同样,由于我们处于同一jvm虚拟机中,因此我们需要继承javax.ejb.ejblocalhome接口。
19. package com.jeffhanson.datatier.ejb;
20.
21. import javax.ejb.createexception;
22. import javax.ejb.finderexception;
23. import javax.ejb.ejblocalhome;
24. import java.util.collection;
25. public interface localuserhome extends ejblocalhome
26. {
27. public localuser create(string userid,
28. string fullname,
29. string address,
30. string city,
31. string state,
32. string zip)
33. throws createexception;
34.
35. public collection findbyfullname(string fullname)
36. throws finderexception;
37.
38. public localuser findbyprimarykey(string userid)
39. throws finderexception;
}
bean类?d?d如果你要开发会话ejb,那么需要实现javax.ejb.sessionbean接口,如果是实体ejb,那么需要实现javax.ejb.entitybean接口(参见列表1
闽公网安备 35060202000074号