|
第5章 实体EJB
实体EJB用在处理客户端请求大量、并发的情况,它在实现业务逻辑的同时,作为数据库的一个缓冲。在服务量大的情况下,减轻数据库的负担,提高业务处理能力。本章介绍实体EJB、两种持久性管理方法、编程模型和实例开发过程。
5.1 实体EJB编程模型
1.实体EJB
实体EJB封装了业务逻辑实现,并且可以供多个客户使用。除了实现业务逻辑外,实体EJB的属性用来代表商业过程中处理的永久性数据。一个简单的实体Bean可以定义成代表数据库表的一个记录,也就是每一个实体对象代表
一条具体的记录。更复杂的实体Bean可以代表数据库表间关联视图。
2.实体EJB的持久性
持久性是实体EJB的一个重要概念。
 图5-1 EJB客户端视图
和会话Bean的编程模型一样,实体EJB的客户端视图也是由主接口和远程接口组成。主接口实现类负责实体对象的创建和查询,远程接口实现类负责逻辑方法的调用。
3.定位一个会话Bean主接口
客户端使用JNDI定位一个实体Bean主接口。例如,Account实体Bean的主接口可使用以下代码进行查找: Context
initialContext = new InitialContext(); AccountHome accountHome
=
(AccountHome) javax.rmi.PortableRemoteObject.narrow(initialContext.lookup("java:comp/env/ejb/accounts"), AccountHome.class); 一个客户端的JNDI命名空间可以配置起来包含网络上在不同机器上的、不同EJB容器中的EJB的主接口。而EJB容器的实际位置对使用企业Bean的客户端来说是透明的。
4.实体Bean主接口
部署在容器中实体Bean的主接口的实现是由容器提供的。并且,容器确保客户端能够通过JNDI访问到部署在容顺中的每个实体Bean的主接口。实现实体Bean主接口的对象是EJBHome。 通过实体Bean主接口,客户端可以进行如下操作: ·创建新的实体对象。 ·查找存在的实体对象。 ·删除实体对象。 ·执行主逻辑方法。 ·获取主接口的句柄。 主句柄能被序列化,并且能被写入存储设备中。然后,句柄可以在另一个不同的JVM中,从固定存储器中反序列化,获取主接口的引用。 实体Bean主接口必须扩展javax.ejb.EJB主接口,并遵循Java语言远程接口规范。
5.create方法
实体Bean主接口可以定义多个create方法,每种方法都能创建一个实体对象。create方法的参数一般用来初始化实体对象的状态。每种create方法名的前缀是“create”。 create方法的返回类型是实体bean的远程接口。每个create方法都要定义抛出两个异常java.rmi.RemoteException和javax.ejb.CreateExcention。也可以包含其它的引用级异常。例如:下面主接口定义中演示了三个create方法:
public Interface AccountHome extends
javax.ejb.EJBHome{ public Account create(String
firstName,String lastName,double initialBalance) throws
RemoteException,CreateException; public Account create(String
accountNumber,double initialBalance) throws
RemoteException,CreateException,LowInitialBalanceException; public
Account createLargeAccount(String firstname,String
lastname, double initialBalance) throws
RemoteException,CreateException; ... } 下面代码演示客户端程序如何创建一个新的实体对象: AccountHome
accountHome =...; Account account =
accountHome.create("John","Smith",500.00);
6.finder方法
实体Bean主接口可以定义一个或多个finder方法,每个方法定义一种查询一个实体EJB和多个EJB对象的方法。 finder方法必须以“find”为前缀,如findLargeAccounts(...),参数由实体Bean的来定位请求的实体对象。finder方法的返回值必须是实体Bean的远程接口,或者是实现实体Bean远程接口对象的集合。定义finder方法的异常有java.rmi.RemoteException和javax.ejb.FinderException。 每个实体Bean的主接口包含一个findByPrimaryKey(primaryKey)方法。它允许客户端使用主键定位一个实体对象,它的名字总是findByPrimaryKey,只有一个参数,这个参数具有和实体Bean主键相同的类型,返回类型是实体Bean的远程接口。每个实体Bean有惟一的findByPrimaryKey(primaryKey)方法,该方法不能被重载,其实现必须确保实体对象存在。下面代码片断演示findByPrimaryKey方法: public
Interface AccountHome extends
javax.ejb.EJBHome{ ... public Account
findByPrimaryKey(String AccountNumber) throws
RemoteException,FinderException; } 下面代码片断演示客户端如何使用findByPrimaryKey方法: AccountHome=...; Account
account = account 主findByPrimaryKey("100-3450-3333");
7.remove方法
javax.ejb.EJBHome接口定义了允许客户端删除实体对象的方法: public Interface
EJBHome extends Remote{ void remove(Handle handle) throws
RemoteException,RemoveException; void remove(Object
primaryKey) throws
RemoteException,RemoveException; } 实体对象删除后,客户端访问实体对象会产生java.rmi.NoSuchObjectException异常。
8.Home方法
实体Bean的主接口可以定义一个或多个主方法。主方法是不特定于某个实体Bean实例业务逻辑方法。主方法的名字必须以“create”、“ind”或“remove”作为开关。主方法的参数被实体Bean的实现类使用,不依赖于某个特定的实体Bean实例。方法的参数和返回值必须是RMI-IIOP的合法类型。 主方法的定义必须招聘java.rmi.RemoteException异常。也可以包括其它引用级异常。 下面代码片断演示两个方法: public
Interface EmployeeHome extends
javax.ejb.EJBHome{ ... public float livingIndex(String
state,float Salary) throws RemoteExcetption; public
void addBonus(float company_share_index) throws
RemoteException,ShareIndexOutOfRangeException; ... }
9.主键和对象标识
每个实体对象有一个惟一的标识。如果两个实体对象有相同的主键,则它们是同一的。EJB架构允许主键是任何合法类型的类。 拥有实体对象远程接口引用的客户端可以通过getPrimaryKey()方法获取主键标识。和引用联系的对象标识在被引用期间不会改变。 客户端可以测试两个实体对象是否指向同一个实体对象,用isIdentical(EJBObject)方法。也可以采用equals方法比较它们的主键。 下面代码片断演示使用isIdentical方法测试指向同一个实体对象的两个对象引用: Account
acc1 = ...; Account acc2 = ...; if
(acc1.isIdentical(acc2)){ //acc和acc2是同一个实体对象 }else{ //acc1和acc2是不同一个实体对象 } 如果客户端知道实体对象的主键,则调用实体Bean主接口的findByPrimaryKey(key)方法,可以获得实体对象的的引用。 注意,比较两个引用是否指向同一个实体对象,不能使用Object.equals(Object
obj)方法,只能使用isIdentical方法。
10.实体Bean的远程接口
客户端通过实体Bean的远程接口访问实体对象。实体Bean的远程接口必须扩展javax.ejb.EJBObject接口。远程接口定义客户端使用的逻辑方法。 下面代码片断演示实体Bean远程接口的定义: public
Interface Account extends javax.ejb.EJBObject{ void
debit(double amount) throws
java.rmi.RemoteException,InsufficientBalanceException; void
credit(double amount) throws
java.rmi.RemoteException; double getBalance() throws
java.rmi.RemoteException; } javax.ejb.EJBObject接口定义允许客户端使用实体对象引用进行,如下操作: ·获取实体对象的主接口。 ·删除实体对象。 ·获取实体对象句柄。 ·获取实对象主键。 容器实现javax.ejb.EJBObject接口中定义的方法,而业务方法以EJB的形式,以代理的方式被调用。 注意 实体对象没有把javax.ejb.EnterpriseBean中定义的方法暴露给客户端,这些方法是被容器调用的。
11.实体Bean的句柄
实体对象的句柄是在网络上标识实体的,拥有实体对象的远程接口客户端可以通过调用getHandle()方法获取实体对象句柄,该句柄类继承java.io.Serializable,所以客户端可以序列化句柄。客户端可以在另一个进程和消息系统中,反序列化该句柄,以重新获得实体对象的引用。 客户端代码必须使用javax.rmi.PortableRemoteObject.narrow(...)方法来把getEJBObject()方法的结果转换成实体Bean远程接口类型。 下面代码片断演示了句柄的使用: //客户端获取account实体句柄,并保存 ObjectOutputStream
stream = ...; Account account = ...; Handle bandle =
account.getHandle(); stream.writeObject(handle); //客户端可以从存储设备中读取句柄,使用句柄获取 //account实体对象的引用 ObjectInputStream
stream = ...; Handle
handle=(Handle)stream.readObject(handle); Account account =
(Account)javax.rmi.PortableRemoteObject.narrow( handle.getEJBObject(),Account.class); account.debit(100.00);
12.实体主句柄
EJB规范允许客户端获取主接口的句柄。客户端把实体Bean的主接口引用以句柄的方式存到存储设备中,然后可以重新获取。当客户端不知道主接口的JNDI名,又想使用主接口,这是个解决的办法。
主接口的句柄必须实现javax.ejb.HomeHandle接口。
客户端代码必须使用java.rmi.PortableRemoteObject.narrow(...)方法来把getEJBHome()方法的结果转化成主接口类型。
|